[Pntool-developers] SF.net SVN: pntool:[245] pnheaders
Brought to you by:
compaqdrew,
miordache
From: <mio...@us...> - 2011-04-02 00:10:32
|
Revision: 245 http://pntool.svn.sourceforge.net/pntool/?rev=245&view=rev Author: miordache Date: 2011-04-02 00:10:24 +0000 (Sat, 02 Apr 2011) Log Message: ----------- 2011 update--second part Added Paths: ----------- pnheaders/ pnheaders/general.c pnheaders/general.h pnheaders/insert.c pnheaders/insert.h pnheaders/main_function.c pnheaders/matrix.c pnheaders/matrix.h pnheaders/pnexample.c pnheaders/pns.c pnheaders/pns.h Added: pnheaders/general.c =================================================================== --- pnheaders/general.c (rev 0) +++ pnheaders/general.c 2011-04-02 00:10:24 UTC (rev 245) @@ -0,0 +1,145 @@ +/**************************************************************************** +GENERAL.C -- general purpose functions +Written in 2008-2009 by M. V. Iordache. +****************************************************************************/ + +#include "general.h" +#include<signal.h> + +void merror(int errorlevel, char* str, ...) { + va_list param; + + fprintf(stderr, "\nERROR!\n"); + va_start(param, str); + vfprintf(stderr, str, param); + va_end(param); + fprintf(stderr, "\n"); + + if(!errorlevel) + raise(SIGINT); /* terminate the entire program */ +} + + +inline void* tmalloc(size_t NBYTES) { + void* p; + p = malloc(NBYTES); + if(p == NULL) + merror(0, "Out of memory"); + return p; +} + + +inline void* tcalloc(size_t N, size_t S) { + void* p; + p = calloc(N, S); + if(p == NULL) + merror(0, "Out of memory"); + return p; +} + + +/* void makezero(void* x, size_t n) { // USE memset instead + int i; + char* p; + for( i = 0, p = (char*)x; i <= n-sizeof(char); i++) + *(p+i) = 0; + } */ + + +/*************************************************************************** + MEMORY MANAGEMENT VIA struct alloc +****************************************************************************/ + +void initalloc(struct alloc* x, size_t N) { + x->N = N; x->mem = tcalloc(N, 1); x->i = N; + x->data = tcalloc(1, sizeof(*(x->data))); + x->data->mem = x->mem; x->pos = x->data; +} + + +inline void* smalloc(struct alloc* x, size_t nbytes) { + /* In this algorithm the memory blocks have at least N bytes and when used + as intended approximately N bytes. */ + + if(!x->N) merror(0, "Uninitialized allocation structure!"); + x->i -= nbytes; + if(x->i >= 0) + return (x->mem) + (x->i); + x->pos->next = tcalloc(1, sizeof(*(x->data))); + x->pos = x->pos->next; + x->mem = tmalloc(x->N + nbytes); x->pos->mem = x->mem; x->i = x->N; + return (x->mem) + (x->i); +} + + +void sfree(struct alloc *x) { + struct _alist *p, *q; + for(p = x->data; p; ) { + free(p->mem); + q = p; + p = p->next; + free(q); + } + x->data = 0; /* no segmentation fault if sfree called twice */ +} + + +/*************************************************************************** + QUEUE ALLOCATION AND MANAGEMENT +****************************************************************************/ + +inline struct _qlist *alloc_qpage(size_t n) { + struct _qlist *p; + p = tmalloc(n + sizeof(*p)); + p->mem = &p[1]; + p->next = 0; + return p; +} + +void qfree(struct qalloc *x) { /* Assumes pages allocated with alloc_qpage! */ + struct _qlist *p; + for(p = x->rrpage; p; p = p->next) + free(p); + x->rrpage = 0; /* no segmentation fault if qfree called twice */ + x->frpage = 0; +} + +void initqalloc(struct qalloc* x, size_t n, size_t sz) { + x->N = n*sz; x->sz = sz; + x->front = (x->N); x->rear = (x->N); + x->frpage = alloc_qpage(x->N); + x->rrpage = x->frpage; x->last = x->frpage; + x->nitems = 0; +} + +inline void* place_in_line(struct qalloc* x) { + (x->nitems)++; + x->front -= x->sz; + if( x->front < 0) { + x->front = x->N - x->sz; + if(x->frpage->next) /* use the next page */ + x->frpage = x->frpage->next; + else { /* allocate a new page if none is available */ + x->frpage->next = alloc_qpage(x->N); + x->frpage = x->frpage->next; + x->last = x->frpage; + } + } + return x->frpage->mem + x->front; +} + +inline void* next_in_line(struct qalloc* x) { + if(x->nitems) { + (x->nitems)--; + x->rear -= x->sz; + if( x->rear < 0 ) { + x->rear = x->N - x->sz; + x->last->next = x->rrpage; /* recycle current page */ + x->last = x->last->next; + x->rrpage = x->rrpage->next; + x->last->next = 0; + } + return x->rrpage->mem + x->rear; + } + return 0; +} Added: pnheaders/general.h =================================================================== --- pnheaders/general.h (rev 0) +++ pnheaders/general.h 2011-04-02 00:10:24 UTC (rev 245) @@ -0,0 +1,98 @@ + +#ifndef GENERAL_H +#define GENERAL_H + +#include<stdio.h> +#include<stdlib.h> +#include<stdarg.h> +#include<string.h> + +void merror(int errorlevel, char* str, ...); +/* Prints error message. str and the following parameters should be formatted + the same way as for printf. + If errorlevel = 0, the SIGINT signal is sent to terminate the program. */ + +inline void* tmalloc(size_t NBYTES); +inline void* tcalloc(size_t N, size_t S); +/* These functions call malloc and calloc, respectively. In addition, they + terminate the program via merror(...) when memory cannot be allocated. */ + +/**************************************************************************/ +/* Memory management for structures that allocate small amounts of memory + at a time */ + +struct _alist { + void* mem; /* pointer to allocated memory */ + struct _alist *next; +}; + + +struct alloc { + size_t N; /* the min size of the blocks of memory will be N + 1 */ + void* mem; /* pointer to current block of allocated memory */ + size_t i; /* indicates number of available bytes in mem */ + struct _alist *data, *pos; /* pos points to the current alist element */ +}; + + +void initalloc(struct alloc* x, size_t N); +/* Must be called before using the allocation object! + N determines the number of bytes of the memory blocks that are allocated. +*/ + +inline void* smalloc(struct alloc* x, size_t nbytes); +/* Use it in the place of malloc. The function is optimized for speed, not for + memory usage. Memory is best used if nbytes is small. The fraction of unused + allocated memory is in the worst case (max(nbytes)-1)/(x->N + 1), where + max(nbytes) is the maximum value given by the program to nbytes. */ + +void sfree(struct alloc *x); +/* Deallocates the memory blocks addressed by the object. */ + +/**************************************************************************/ +/* Memory management for queues */ + +struct _qlist { + void* mem; /* pointer to allocated memory */ + struct _qlist *next; +}; + + +/* The structures is organized in blocks of memory called here pages. Each + page can store N bytes. A page stores elements of size sz bytes. */ +struct qalloc { + size_t N, sz; /* N: bytes per page, sz: bytes per element */ + size_t front, rear; /* front: position of last element; + rear: position of first element; */ + size_t nitems; /* number of items in the queue */ + struct _qlist *frpage, *rrpage; /*the pages of front and rear, respectively*/ + struct _qlist *last; /* pointer to the last element of the chain of pages */ + + /* Note that rrpage always points to the first page of the chain. Once all + elements on a page have been removed, the empty page is placed at the end + of the chain and rrpage points to the new first page of the chain. + + Each time a new element is added to the queue, front -= sz, until front + becomes negative. Then, frpage is set to the next page. If there is no + next page, a new page is allocated. + */ +}; + +void initqalloc(struct qalloc* x, size_t n, size_t sz); +/* Must be called before using the allocation object! + n: number of elements of (max) size sz per block of memory. +*/ + +inline void* place_in_line(struct qalloc* x); +/* Places a new element in line and returns a pointer to it. */ + +inline void* next_in_line(struct qalloc* x); +/* Removes from queue the element returned in the previous call (the + first element in line) and returns the next element in line. The return + value is in the form of a pointer to the element. The pointer is null if + no element remains in line. */ + +void qfree(struct qalloc *x); +/* Deallocates the memory blocks addressed by the object. */ + +#endif Added: pnheaders/insert.c =================================================================== --- pnheaders/insert.c (rev 0) +++ pnheaders/insert.c 2011-04-02 00:10:24 UTC (rev 245) @@ -0,0 +1,291 @@ +/* INSERT.C: Only one task may use these function at a time. Variables + must be reinitialized each time a new task begins to use it. */ + +#include"insert.h" +#include<stdlib.h> +#include<string.h> + +/* defined in insert.h + struct myinsert { + long INCR; + long strg_size, strg_len; + char* strg, *tmp, stmp[10], *IndString; + }; */ + +struct myinsert InitInsert(int i) { + struct myinsert ret; + memset(&ret, 0, sizeof(ret)); + if (i < 2) + ret.INCR = BUFINC; + else + ret.INCR = i; + ret.strg_size = 0; + ret.strg_len = 0; + ret.strg = 0; + return ret; +} + +char* GetInsertBuf(struct myinsert* s) { + return s->strg; +} + + +void Empty(struct myinsert* s) { + if(s) { + if(s->strg) + if(s->strg_size) { + s->strg_len = 0; + s->strg[0] = 0; + } + if(s->IndString) + free(s->IndString); + s->IndString = 0; + } +} + + +void FreeIns(struct myinsert* s) { // does not free the main buffer + long x; + + if(s) { + x = s->INCR; + if(s->IndString) + free(s->IndString); + memset(s, 0, sizeof(*s)); + s->INCR = x; + } +} + + +struct myinsert AddToIndent(struct myinsert ins, int n) { + int k; + char *sa; + + if(!ins.IndString && n <= 0) + return ins; + if(!ins.IndString) { // here n > 0 + ins.IndString = calloc(n+1, sizeof(char)); // initializes data to zero + memset(ins.IndString, ' ', n); + return ins; + } + k = strlen(ins.IndString); + if(k + n <= 0) { + free(ins.IndString); + ins.IndString = 0; + return ins; + } + + if(n > 0) { + sa = calloc(k+n+1, sizeof(char)); + strcpy(sa, ins.IndString); + memset(sa+k, ' ', n); + free(ins.IndString); + ins.IndString = sa; + } + + ins.IndString[k+n] = 0; // all that is needed when n < 0 + + return ins; +} + + +struct myinsert FSInsert(struct myinsert ins, const char *str, ...) { + char* p; + va_list param; + + if(str) + if(strlen(str)) { + va_start(param, str); + vasprintf(&p, str, param); + va_end(param); + + ins = SInsert(p, ins); + + free(p); + } + return ins; +} + + + +struct myinsert SInsert_sub(char* s, size_t k, struct myinsert ins) { + // k is the length of s (without the final 0 element) + + long i, j; + + if(!s) + return ins; + i = ins.strg_len; + if(k <= 0) + return ins; + ins.strg_len += k; + if(ins.strg_size <= ins.strg_len + 1) { + for(; ins.strg_size <= ins.strg_len + 1; ins.strg_size += ins.INCR); + if(!ins.strg) { + ins.strg = calloc(ins.strg_size, sizeof(*ins.strg)); + if(!ins.strg) { + printf("Sinsert: unable to allocate %ld bytes\n", ins.strg_size); + exit(EXIT_FAILURE); + } + strcpy(ins.strg, s); + return ins; + } + else { /* if more memory is needed */ + ins.tmp = calloc(ins.strg_size, sizeof(*ins.strg)); + if(!ins.tmp) { + printf("Sinsert: unable to allocate %ld bytes\n", ins.strg_size); + exit(EXIT_FAILURE); + } + strcpy(ins.tmp, ins.strg); + free(ins.strg); + ins.strg = ins.tmp; + } + } + for(j = 0; i + j < ins.strg_len; j++) /* concatenate the strings */ + ins.strg[i+j] = s[j]; + ins.strg[i+j] = 0; + + return ins; +} + + + +struct myinsert CInsert(char c, struct myinsert ins) { + if(c == 0) + return ins; + if(ins.strg_size <= ins.strg_len + 1) { + ins.strg_size += ins.INCR; + if(!ins.strg) { + ins.strg = calloc(ins.strg_size, sizeof(*ins.strg)); + if(!ins.strg) { + printf("Cinsert: unable to allocate %ld bytes\n", ins.strg_size); + exit(EXIT_FAILURE); + } + } + else { + ins.tmp = calloc(ins.strg_size, sizeof(*ins.tmp)); + if(!ins.tmp) { + printf("Cinsert: unable to allocate %ld bytes\n", ins.strg_size); + exit(EXIT_FAILURE); + } + strcpy(ins.tmp, ins.strg); + free(ins.strg); + ins.strg = ins.tmp; + } + } + ins.strg[ins.strg_len++] = c; /* update ins.strg and ins.strg_len */ + ins.strg[ins.strg_len] = 0; + + if(c == '\n' && ins.IndString) + ins = SInsert_sub(ins.IndString, strlen(ins.IndString), ins); + + return ins; +} + + + +struct myinsert SInsert(char* s, struct myinsert ins) { + long i, j; + size_t k; + char c; + + if(!s) + return ins; + k = strlen(s); + if(!k) + return ins; + if(!ins.IndString) { + ins = SInsert_sub(s, k, ins); + } + else { + for(i = 0, j = 0; i < k; i++) { + if(s[i] == '\n') { + ins = SInsert_sub(s+j, i-j+1, ins); // insert s[j] ... s[i] + j = i+1; + ins = SInsert_sub(ins.IndString, strlen(ins.IndString), ins); + } + } + if(j < i) // insert remaining part of string, if any is left + ins = SInsert_sub(s+j, k-j, ins); // insert s[j] ... s[k-1] + } + return ins; +} + + + long INCR = BUFINC; + long strg_size = 0, strg_len = 0; + char* strg = 0, *tmp, stmp[10]; + + +void init_insert() { + strg_size = 0; strg_len = 0; strg = 0; +} + +char* get_insert_buf() { + return strg; +} + +void cinsert(char c) { + if(c == 0) + return; + if(strg_size <= strg_len + 1) { + strg_size += INCR; + if(!strg) { + strg = calloc(strg_size, sizeof(*strg)); + if(!strg) { + printf("Cinsert: unable to allocate %ld bytes\n", strg_size); + exit(EXIT_FAILURE); + } + } + else { + tmp = calloc(strg_size, sizeof(*tmp)); + if(!tmp) { + printf("Cinsert: unable to allocate %ld bytes\n", strg_size); + exit(EXIT_FAILURE); + } + strcpy(tmp, strg); + free(strg); + strg = tmp; + } + } + strg[strg_len++] = c; /* update strg and strg_len */ + strg[strg_len] = 0; +} + + +void sinsert(char* s) { + long i, j; + size_t k; + if(!s) + return; + i = strg_len; + k = strlen(s); + if(!k) + return; + strg_len += k; + if(strg_size <= strg_len + 1) { + for(; strg_size <= strg_len + 1; strg_size += INCR); + if(!strg) { + strg = calloc(strg_size, sizeof(*strg)); + if(!strg) { + printf("Sinsert: unable to allocate %ld bytes\n", strg_size); + exit(EXIT_FAILURE); + } + strcpy(strg, s); + return; + } + else { /* if more memory is needed */ + tmp = calloc(strg_size, sizeof(*strg)); + if(!tmp) { + printf("Sinsert: unable to allocate %ld bytes\n", strg_size); + exit(EXIT_FAILURE); + } + strcpy(tmp, strg); + free(strg); + strg = tmp; + } + } + for(j = 0; i + j < strg_len; j++) /* concatenate the strings */ + strg[i+j] = s[j]; + strg[i+j] = 0; +} Added: pnheaders/insert.h =================================================================== --- pnheaders/insert.h (rev 0) +++ pnheaders/insert.h 2011-04-02 00:10:24 UTC (rev 245) @@ -0,0 +1,49 @@ +#ifndef INSERT_H +#define INSERT_H + +#include<stdarg.h> + +#define BUFINC 10024 + +struct myinsert { + long INCR; + long strg_size, strg_len; + char* strg, *tmp, stmp[10], *IndString; +}; + +/* These insert functions work with any number of buffers at the same time */ + +struct myinsert InitInsert(int i); +/* i: size increment of allocation buffer; use i = 0 for the default value */ + +struct myinsert AddToIndent(struct myinsert ins, int n); +/* Adds n blank spaces to default indentation; n may be negative. */ + +struct myinsert CInsert(char c, struct myinsert ins); + +struct myinsert SInsert(char* s, struct myinsert ins); + +struct myinsert FSInsert(struct myinsert ins, const char *str, ...); +/* Same as SInsert except it can use a printf formatted string */ + +char* GetInsertBuf(struct myinsert* s); +/*gets the result; this should be deallocated with free() if no longer needed*/ + +void Empty(struct myinsert* s); +/* Use this function if buffer should be reused. It empties the buffer without + deallocating it. Resets also indentation. */ + +void FreeIns(struct myinsert* s); +/* Does not deallocate the buffer, which is the responsibility of the user. */ + +/* These insert functions work with ONE buffer ONLY at a time */ + +void init_insert(); + +void cinsert(char c); + +void sinsert(char* s); + +char* get_insert_buf(); + +#endif Added: pnheaders/main_function.c =================================================================== --- pnheaders/main_function.c (rev 0) +++ pnheaders/main_function.c 2011-04-02 00:10:24 UTC (rev 245) @@ -0,0 +1,304 @@ +#include "pns.h" +#include "spnbox.h" +#include "codegen.h" +#include"insert.h" + +int verb; + +int inline is_verbose() { return verb; } + +void br_filter(char *p) { // removes beginning and end braces + int n; + if(!p) + return; + n = strlen(p); + if(!n) + return; + n--; + if(p[0] == '{' && p[n] == '}') { + p[0] = ' '; + p[n] = ' '; + } +} + + +int is_empty(char *p) { // returns 1 if p has only space and tab characters + int i; + if(!p) return 1; + for(i = 0; p[i]; i++) + if(p[i] != ' ' && p[i] != '\t') + break; + return ! p[i]; +} + +int th_filter(char** ap) { // filters <thread> commands + char* p = *ap, *p2 = 0; + int i; + if(!p) return 0; + 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); + free(*ap); + *ap = p2; + return 1; + } + break; + } + return 0; +} + + +void sp_filter(specs *sp) { + // Removes beginning and end braces. + // Processes <thread> instructions. + int i, j; + pns *pn; + arcs *pa; + if(!sp) + return; + if(!sp->process_array) + return; + for(i = 0; i < sp->process_num; i++) { + if(!sp->process_array[i]) + 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; + pn = sp->process_array[i]->pn; + if(pn) { + if(pn->segment) + for(j = 0; j < pn->pnum; j++) + br_filter(pn->segment[j]); + if(pn->select) + for(j = 0; j < pn->pnum; j++) + br_filter(pn->select[j]); + if(pn->arc_list) + for(j = 0; j < pn->tnum; j++) + for(pa = pn->arc_list[j]; pa; pa = pa->next) + br_filter(pa->condition); + } + } +} + + +int main(int na, char* argv[]) { + + int i, j, l1, l2, UCcnt, UOcnt, *Tuc, *Tuo, *UClst, *UOlst; + int labelcount = 0, finish = 0; + char* input, *build; + FILE* f; + specs *sp; + syncc *snc; + pns pn, *apnsv; + matrix L, C, H; + int *B; + struct myinsert ins; + linenf_r lin_res; + struct synclist *syncl, *syncl2; + struct sync_element *syn_el, *syn_el2; + struct label_lst* lls; + TrData** TInf; + + + ins = InitInsert(512); // used to store command line parameters + verb = 0; + input = 0; + + if(na <= 1 || na > 3) { + printf("\nACTS--A Concurrency Tool Suite for concurrent programming and concurrent \nsystem design. This software is part of ongoing research to apply supervisory\ncontrol and related approaches to concurrency problems. While various \nsupervisory control tools should be implemented in the future, currently only\nmethods of the supervision based on place invariants are implemented. For \nmore information please refer to the documentation.\n\ +\nUsage: ct [-dnum] file [-b ...]\ +\nOptions:\ +\n -b ... List of files and compiler options that should be copied to\ +\n the command line that builds the main program.\ +\n -d<num> Comment on execution progress. More information displayed for\ +\n high values of <num>.\ +\n\ +\nExamples: ct manf.sp\ +\n ct -d3 input.sp\n"); + + finish = 1; + } + + for(i = 1; i < na && !finish; i++) { + if(argv[i][0] == '-') { + switch(argv[i][1]) { + case 'd': verb = atoi(argv[i]+2); + break; + case 'b': if(argv[i][2]) + ins = FSInsert(ins, " %s", argv[i]+2); + for(i = i + 1; i < na; i++) + ins = FSInsert(ins, " %s", argv[i]); + break; + default: fprintf(stderr, "Unknown option %s.\n", argv[i]); + } + } + else { + if(input) + fprintf(stderr, "Unexpected parameter %s.\n", argv[i]); + else + input = argv[i]; + } + } + + if(!input) { + fprintf(stderr, "No input file specified."); + finish = 1; + } + else { + f = fopen(input,"r"); + if(!f) { + fprintf(stderr, "The file %s cannot be opened.\n", input); + finish = 1; + } + else { + if(verb && !finish) + fprintf(stderr, "Using the input file %s ...\n", input); + fclose(f); + } + } + + build = GetInsertBuf(&ins); + + if(finish) { // Terminate if errors were encountered + if(build) free(build); + return 0; + } + + // Call the translator + + sp = ScanInput(input); + if(!sp) // check translator result + return 1; + if(sp->process_num <= 0) { + fprintf(stderr, "No processes defined! Nothing to do.\n"); + dealloc_specs(sp); + if(build) free(build); + return 0; + } + + sp_filter(sp); // 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); + displaypn(*(sp->process_array[i]->pn), stdout); + } + } + + + // Label the PNs + + for(i = 0; i < sp->process_num; i++) + updatepn(sp->process_array[i]->pn, "freelabel", &labelcount); + + // 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) { + l1 = snc->pn1->t[snc->t1].l; l2 = snc->pn2->t[snc->t2].l; + if(l1 != l2) { + i = 1; + j = (l1 > l2)?l1:l2; + snc->pn1->t[snc->t1].l = j; snc->pn2->t[snc->t2].l = j; + } + } + + // 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); + + if(is_verbose() >= 3) { // For debugging + printf("\n\n======================================================"); + printf("\nCONSTRAINTS:\n"); + printLHCB(&pn, &L, &H, &C, B, -1, stdout); + } + + // Perform SC + + Tuc = tcalloc(pn.tnum, sizeof(*Tuc)); + Tuo = tcalloc(pn.tnum, sizeof(*Tuo)); + if(pn.t) + for(i = 0; i < pn.tnum; i++) { + Tuc[i] = pn.t[i].uncontrollable; + Tuo[i] = pn.t[i].unobservable; + } + + UCcnt = findIndices(Tuc, pn.tnum, sizeof(*Tuc), &UClst); + UOcnt = findIndices(Tuo, pn.tnum, sizeof(*Tuo), &UOlst); + + lin_res = linenf(&pn.out, &pn.in, &L, B, pn.marking, &H, &C, \ + UCcnt, UClst, UOcnt, UOlst); + + if(is_verbose() >= 3) { // For debugging + printf("\n\n======================================================"); + printf("\nADMISSIBLE CONSTRAINTS (H entries omitted): \n"); + 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 + + // no liveness enforcement at this time + + // 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"); + displaypn(pn, stdout); + printf("\n\n======================================================"); + if(apnsv) { + printf("\nSUPERVISOR PN\n"); + displaypn(*apnsv, stdout); + } + else + printf("\nNO SUPERVISOR PN\n"); + } + deallocpn(&pn); + + // need functions to free linenf_r structures and similar structures + + // Generate code + + + + // Obtain also a synclist structure with the sync data + 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); + + CodeGenerator(apnsv, sp->name, sp->process_array, sp->process_num,\ + syncl, TInf, build); + + // Free memory + + if(apnsv) { + deallocpn(apnsv); + free(apnsv); + } + dealloc_specs(sp); + if(build) free(build); + free_label_list(lls); + free_synclist(syncl); + free_TrData(TInf, sp->process_num); + + return 0; +} + Added: pnheaders/matrix.c =================================================================== --- pnheaders/matrix.c (rev 0) +++ pnheaders/matrix.c 2011-04-02 00:10:24 UTC (rev 245) @@ -0,0 +1,512 @@ +/**************************************************************************** +MATRIX.C +Written in 2008-2009 by M. V. Iordache. +****************************************************************************/ + +#include "pns.h" + +MatrElem* FindEl(const matrix* m, int i, int j, MatrElem** next, int dir) { + /* THE FUNCTION TAKES IN ACCOUNT THE trans FIELD OF m! + It finds a pointer to the element (i,j) if it has a MatrElem object in the + matrix. Otherwise it returns zero. The search is done in the direction + indicated by 'dir', which can be one of mDOWN, mUP, mRIGHT, or mLEFT. + The function writes to '*next' the element next to the (i,j) position in + the direction indicated by 'dir'. If no other element is present, *next + is made zero. + */ + + int ii, jj, k = -1; /* k must be initialized to a value less than 0 */ + MatrElem* p; + + if(m->type != 3 || m->nc <= 0 || m->nr <= 0) { + merror(0, "FindEl: The operation is not implemented."); + return 0; + } + + dir = dir^m->trans; /* xor with m->trans to correct direction */ + + if(m->trans) { + ii = j; jj = i; + } + else { + ii = i; jj = j; + } + + if(!(dir&1)) {/* that is, if(dir == mRIGHT || dir == mLEFT) */ + p = m->row[ii]; + if(p) { + for( ; (k < p->column) && (jj > p->column); p = p->next[mRIGHT]) + k = p->column; + + if(p->column == jj) { + *next = p->next[dir]; + return p; + } + if(dir == mLEFT) { /* else *next will be set to p in a subsequent line */ + *next = p->next[mLEFT]; + return 0; + } + } + } + else {/* that is, if(dir == mDOWN || dir == mUP) */ + p = m->column[jj]; + if(p) { + for( ; (k < p->row) && (ii > p->row); p = p->next[mDOWN]) + k = p->row; + + if(p->row == ii) { + *next = p->next[dir]; + return p; + } + if(dir == mUP) { /* else *next will be set to p in a subsequent line */ + *next = p->next[mUP]; + return 0; + } + } + } + *next = p; + return 0; +} + +inline mtype _matrel3(const matrix* m, int i, int j) { + MatrElem *p, *next; + + p = FindEl(m, i, j, &next, mRIGHT); + if(!p) + return 0; + return p->value; +} + +mtype GetMatrixEl(const matrix* m, int i, int j) { + switch(m->type) { + case 1: + return m->trans?m->elem[j*m->nc+i]:m->elem[i*m->nc+j]; + case 2: + return m->trans?m->ar[j][i]:m->ar[i][j]; + case 3: + return _matrel3(m, i, j); + default: + merror(0, "MATRIX: The operation is not implemented."); + } + return 0; +} + + + +inline void _setmatrel3(const matrix* m, int i, int j, mtype x) { + int ii, jj; + int dir; + MatrElem *p, *next, *next2; + + /* If an already allocated element is set to zero it is not deleted + (deallocated) in this version of the function. */ + + p = FindEl(m, i, j, &next, mRIGHT); /* signals error if m->nr or m->nc = 0 */ + if(p) { /* if the element has been already allocated */ + p->value = x; + return; + } + + /* The following lines executed if element (i,j) not allocated in matrix. */ + + if(!x) /* nothing to do if the element is not allocated and x = 0 */ + return; + + /* Create and initialize new element of the matrix */ + + p = tmalloc(sizeof(*p)); + p->value = x; + if(m->trans) {/*ii and jj: row and column number in internal representation*/ + ii = j; jj = i; + } + else { + ii = i; jj = j; + } + p->column = jj; + p->row = ii; + + /* Place element in matrix */ + + if(!next) { + if(m->trans){/*if transposed, search to mRIGHT in FindEl is to mDOWN in m*/ + m->column[jj] = p; + p->next[mDOWN] = p; + p->next[mUP] = p; + } + else { + m->row[ii] = p; + p->next[mRIGHT] = p; + p->next[mLEFT] = p; + } + } + else { + dir = mRIGHT^(m->trans);/*next obtained by a search in the mRIGHT direction*/ + p->next[dir] = next; /*dir = mDOWN or mRIGHT depending on trans = 1 or 0 */ + p->next[dir^2] = next->next[dir^2]; /* dir^2 = mUP or mLEFT */ + next->next[dir^2]->next[dir] = p; + next->next[dir^2] = p; + } + + FindEl(m, i, j, &next2, mDOWN); + if(!next2) { + if(m->trans){/*if transposed, search to mDOWN in FindEl is to mRIGHT in m*/ + m->row[ii] = p; + p->next[mRIGHT] = p; + p->next[mLEFT] = p; + } + else { + m->column[jj] = p; + p->next[mDOWN] = p; + p->next[mUP] = p; + } + } + else { + dir = mDOWN^(m->trans);/*next2 obtained by a search in the DOWN direction*/ + p->next[dir] = next2; /*dir = mDOWN or mRIGHT depending on trans = 1 or 0*/ + p->next[dir^2] = next2->next[dir^2]; /* dir^2 = mUP or mLEFT */ + next2->next[dir^2]->next[dir] = p; + next2->next[dir^2] = p; + } + + /* update row and column to point to the first element in chain */ + if(m->row[ii]->column > p->column) + m->row[ii] = p; + if(m->column[jj]->row > p->row) + m->column[jj] = p; +} + +void SetMatrixEl(matrix* m, int i, int j, mtype x) { + switch(m->type) { + case 1: + if(m->trans) + m->elem[j*m->nc+i] = x; + else + m->elem[i*m->nc+j] = x; + break; + case 2: + if(m->trans) + m->ar[j][i] = x; + else + m->ar[i][j] = x; + break; + case 3: + _setmatrel3(m, i, j, x); + break; + default: + merror(0, "MATRIX: The operation is not implemented."); + } +} + + +inline MatrElem* NextEl(const matrix* m, int dir, int pos, MatrElem* current) { + /* Finds the next element on the row or column 'pos' (depending on 'dir'). + Returns 0 if no other element is in the specified direction. */ + /* This function is for type 3 matrices in which not all elements are + allocated in memory. Thus, the function returns the next allocated + allocated element. */ + /* If called within a loop, the function will give the right result if + the matrix chains are not modified between calls. */ + /* It does not verify that pos and current->row/column are consistent! */ + /* 'dir' is one of mRIGHT, mLEFT, mUP, mDOWN; the next element is searched + on the row 'pos' if 'dir' is mRIGHT or mLEFT and else on the column 'pos'. + */ + /* Here is an example on how this function could be used in a loop: + p = 0; + for(p = NextEl(&(pn1.in),mUP,i,p); p; p = NextEl(&(pn1.in),mUP,i,p)) { + if(pn1.in.trans) // pn1 is transposed! + SetMatrixEl(&(pn.in), p->column, i, p->value); + else + SetMatrixEl(&(pn.in), p->row, i, p->value); + } + */ + MatrElem *p, *pt, **pbase; + + if(m->type != 3) { + merror(0, "NextEl: The operation is not implemented."); + return 0; + } + dir = dir^m->trans; /* xor with m->trans to correct direction */ + + if(!(dir&1)) /* that is, if(dir == mRIGHT || dir == mLEFT) */ + pbase = m->row; + else /* that is, if(dir == mUP || dir == mDOWN) */ + pbase = m->column; + + p = pbase[pos]; + if(!current) + return p; + if(!p) + return 0; /* no (allocated) elements on the row, so return 0. */ + pt = current->next[dir]; + if(p == pt) + return 0; /* all elements of the chain have been visited, so return 0 */ + return pt; +} + + +void AllocateMatrix(matrix* m, int nr, int nc) { + if(nr*nc <= 100) + AllocateMatrixType(1, m, nr, nc); + else + AllocateMatrixType(2, m, nr, nc); +} + + +void AllocateMatrixType(int type, matrix* m, int nr, int nc) { + int i; + + memset(m, 0, sizeof(matrix)); /* Initializes to zero the structure */ + m->nr = nr; + m->nc = nc; + m->type = type; + + if(!nr || !nc) + return; + + switch(type) { + case 1: + m->elem = tcalloc(nc*nr, sizeof(mtype)); + return; + case 2: + m->ar = tcalloc(nr, sizeof(mtype*)); + for(i = 0; i < nr; i++) + m->ar[i] = tcalloc(nc, sizeof(mtype)); + return; + case 3: + m->row = tcalloc(nr, sizeof(*(m->row))); + m->column = tcalloc(nc, sizeof(*(m->column))); + return; + default: + merror(0, "MATRIX: The operation is not implemented."); + } +} + + + +void Copy2ZeroColumn(const matrix* src, int i, matrix* dst, int k, int offset){ + /* Copies the allocated elements of column i of src to the column k of dst. + Namely, it does dst[offset + j][k] = src[j][i] for all j such that + src[j][i] is allocated. Now, IF the column k of dst is zero, this means + that we copy the column i of src to the column k of dst. This function + is intended for type 3 matrices. + + Example: When a Petri net object pn1 is copied to a new Petri net object + pn, we could copy the column i of the input matrix of pn1 as follows: + Copy2ZeroColumn(&(pn1.in),i,&(pn.in),i,0); + */ + + MatrElem* p = 0; /* it is essential that p is initialized to zero */ + int j; + + if(src->type == 3) { + for(p = NextEl(src,mUP,i,p); p; p = NextEl(src,mUP,i,p)) { + if(src->trans) /* */ + SetMatrixEl(dst, offset + (p->column), k, p->value); + else + SetMatrixEl(dst, offset + (p->row), k, p->value); + } + } + else + for(j = 0; j < NumberOfRows(*src); j++) + SetMatrixEl(dst, offset + j, k, GetMatrixEl(src,j,i)); +} + + +void MakeZeroColumn(matrix* dst, int col) { + /* Makes zero the column col of dst. The implementation could be optimized if + needed. */ + + int i, n; + n = NumberOfRows(*dst); + for(i = 0; i < n; i++) + SetMatrixEl(dst, i, col, 0); +} + +void MakeZeroRow(matrix* dst, int num) { + /* Makes zero the row num of dst. The implementation could be optimized if + needed. */ + + int i, n; + n = NumberOfColumns(*dst); + for(i = 0; i < n; i++) + SetMatrixEl(dst, num, i, 0); +} + + +void CopyBlock(int nx, int ny, const matrix* src, int xs, int ys,\ + matrix* dst, int xd, int yd) { + /* Copies a block of nx by ny elements of src to dst. Specifically, it + copies the elements (xs+i, ys+j) of src to (xd+i, yd+j) of dst for all + i = 0...nx-1 and j = 0...ny-1. */ + int i, j; + + /* This is a plain implementation; it could be optimized in the future */ + + switch(src->type) { + case 3: + /* if(dst->type != 3) { + for(i = 0; i < nx; i++) { + p = NextEl(src, mRIGHT, i+xs, 0); + if(!p) { // all elements are zero + for(j = 0; j < ny; j++) + SetMatrixEl(dst, i+xd, j+yd, 0); + } + ... + for(j = 0; j < ny; j++) { + if(src->trans) { // rows actually columns + if(j <= (p->row - yd)) + } + } + } + } */ + default: + for(i = 0; i < nx; i++) + for(j = 0; j < ny; j++) + SetMatrixEl(dst, i+xd, j+yd, GetMatrixEl(src, i+xs, j+ys)); + } +} + + +void CopyMatrix(const matrix* src, matrix* dst) { + CopyBlock(NumberOfRows(*src), NumberOfColumns(*src), src, 0, 0, dst, 0, 0); +} + + +int** matrix2array(matrix mat) { +/* Converts a matrix object to an array of integers: result[i][j] = elem(i,j)*/ + int** res, i, j; + res = tmalloc(sizeof(int*)*mat.nr); + for(i = 0; i < mat.nr; i++) { + res[i] = tmalloc(sizeof(int)*mat.nc); + for (j = 0; j < mat.nc; j++) + res[i][j] = GetMatrixEl(&mat, i, j); + } + return res; +} + + +int** vector2array(int* v, int nr, int nc) { + int** res, i, j; + res = tmalloc(sizeof(int*)*nr); + for(i = 0; i < nr; i++) { + res[i] = tmalloc(sizeof(int)*nc); + for (j = 0; j < nc; j++) + res[i][j] = v[i*nc + j]; + } + return res; +} + + +matrix array2matrix(int** ar, int nr, int nc) { + matrix m; + int i, j, k; + + AllocateMatrix(&m, nr, nc); + for(i = 0; i < nr; i++) + for(j = 0; j < nc; j++) + SetMatrixEl(&m, i, j, ar[i][j]); + + return m; +} + +matrix vector2matrix(int* v, int nr, int nc) { + matrix m; + int i, j, k; + + AllocateMatrix(&m, nr, nc); + for(i = 0, k = 0; i < nr; i++) + for(j = 0; j < nc; j++, k++) + SetMatrixEl(&m, i, j, v[k]); + + return m; +} + + + +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 + return value is the number of nonzero indices. Further, the indices are + stored in 'answer'. Note that *answer is a pointer to memory allocated + in this function. Memory is always allocated, even if there are no indices. + + This function is similar to the find function of Matlab. */ + + int count, i, j; + void* p; + + *answer = tcalloc(n, sizeof(int)); + + if(sizeof(char) != 1) + merror(0, "findIndices has to be rewritten!"); + + for(count = 0, i = 0, p = vect; i < n; i++, p+= esize) + for(j = 0; j < esize; j++) + if( *(char*)( p + j ) ) { + (*answer)[count++] = i; + break; + } + + return count; +} + + + +void free2Darray(int** ar, int nr) { +/* Used to deallocate an array created with matrix2array or vector2array; nr is the number of rows */ + + int i; + for(i = 0; i < nr; i++) + free(ar[i]); + free(ar); +} + + +void inline _delmatr3(matrix* m) { + int i; + MatrElem* p, *pt; + for (i = 0; i < (m->nr); i++) { + p = m->row[i]; + if(p) { + p->next[mLEFT]->next[mRIGHT] = 0; + while(p) { + pt = p->next[mRIGHT]; + free(p); + p = pt; + } + } + } + free(m->row); + free(m->column); +} + +void DeallocateMatrix(matrix* m) { + switch(m->type) { + case 1: + if(m->nr && m->nc && m->elem) + free(m->elem); + break; + case 2: + if(m->nr && m->nc) + free2Darray((int**) (m->ar), (int) m->nr); + break; + case 3: + if(m->nr && m->nc) { + _delmatr3(m); + } + break; + default: + merror(0, "MATRIX: The operation is not implemented."); + } + memset(m, 0, sizeof(*m)); +} + + +/* To do: + - _setmatrel3 does not deallocate elements set to zero + - consider better matrix representations. For instance, for type 3 + matrices, consider better representations of row and column than + int*. The improvements are to be intended for a more effient + representation of very large matrices. + - CopyBlock could be optimized for type 3 matrices. +*/ Added: pnheaders/matrix.h =================================================================== --- pnheaders/matrix.h (rev 0) +++ pnheaders/matrix.h 2011-04-02 00:10:24 UTC (rev 245) @@ -0,0 +1,143 @@ +#ifndef _MATRIX_H +#define _MATRIX_H + +#include "general.h" + +typedef short int mtype; + +/* The following structure useful for matrices in which most elements are 0. */ +typedef struct MatrElem { + mtype value; /* the value of a (nonzero) element */ + int row, column; /* position of element in the matrix */ + struct MatrElem *next[4]; + /* these are pointers to the next (nonzero) elements of the matrix in + the four directions: down, up, right, left */ +} MatrElem; + +/* the following values must not be changed unless the functions performing + the basic operations on MatrElem are also updated */ +#define mDOWN 1 +#define mUP 3 +#define mRIGHT 0 +#define mLEFT 2 + +typedef struct matrix { + int nc; /* number of columns */ + int nr; /* number of rows */ + unsigned int type:3; /* indicates the type of matrix representation */ + unsigned int trans:1; /* indicates whether the matrix is transposed */ + /* when the matrix is transposed, the element (i,j) of the matrix is + interpreted as the element (j,i). */ + union { + mtype *elem; /* matrix representation for type = 1 */ + /* nr*nc elements in this order: row 1, row 2, row 3, ... */ + /* If trans = 0, it is not transposed: elem(i,j) = elem[i*nc + j]. + Otherwise, it is transposed: elem(i,j) = elem[j*nc + i]. */ + + mtype **ar; /* matrix representation for type = 2 */ + + struct { /* matrix representation for type = 3 */ + MatrElem** row; + MatrElem** column; + /* rows and columns organized as chains; for instance, row[i] contains + the address of the first element of the chain on row i. */ + }; + }; +} matrix; + +/* Avoid modifying directly a matrix object. + Use instead the following functions: + - AllocateMatrix (for memory allocation and initialization). + - GetMatrixEl (to obtain the value of the element (i,j) of the matrix). + - SetMatrixEl (to write a number to the element (i,j) of the matrix). + - DeallocateMatrix (to deallocate the memory used by the matrix). +*/ + +void AllocateMatrix(matrix* m, int nr, int nc); +/* This is the first step when defining a matrix. Specify the number of + rows (nr) and the number of columns (nc). Then, the function will allocate + memory to represent the matrix. Moreover, the data will be initialized with + zero (by means of calloc). + + The function selects automatically the matrix type and then calls + AllocateMatrixType */ + +mtype GetMatrixEl(const matrix* m, int i, int j); +/* Returns the element (i,j) of the matrix */ + +void SetMatrixEl(matrix* m, int i, int j, mtype x); +/* Writes x to the element (i,j) of the matrix */ + +#define NumberOfRows(m) ((m).trans?(m).nc:(m).nr) + +#define NumberOfColumns(m) ((m).trans?(m).nr:(m).nc) + +#define MatrixLength(m) ((m).nr*(m).nc) + +void DeallocateMatrix(matrix* m); + +void CopyMatrix(const matrix* src, matrix* dst); +/* The function assumes that dst has been already allocated ! */ + +void CopyBlock(int nx, int ny, const matrix* src, int xs, int ys,\ + matrix* dst, int xd, int yd); +/* Copies a block of nx by ny elements of src to dst. Specifically, it + copies the elements (xs+i, ys+j) of src to (xd+i, yd+j) of dst for all + i = 0...nx-1 and j = 0...ny-1. */ + +void Copy2ZeroColumn(const matrix* src, int i, matrix* dst, int k, int offset); + /* This function is for type 3 matrices. + Copies the allocated elements of column i of src to the column k of dst. + Namely, it does dst[offset + j][k] = src[j][i] for all j such that + src[j][i] is allocated. Now, IF the column k of dst is zero, this means + that we copy the column i of src to the column k of dst. + + Example: When a Petri net object pn1 is copied to a new Petri net object + pn, we could copy the column i of the input matrix of pn1 as follows: + Copy2ZeroColumn(&(pn1.in),i,&(pn.in),i,0); + */ + +void MakeZeroColumn(matrix* dst, int i); +/* Makes zero the column i of dst. */ + +void MakeZeroRow(matrix* dst, int i); +/* Makes zero the row i of dst. */ + +void AllocateMatrixType(int type, matrix* m, int nr, int nc); +/* Allocates the memory required for an nr by nc matrix. Does not deallocate + memory if already allocated. */ + +MatrElem* NextEl(const matrix* m, int dir, int pos, MatrElem* current); +/* Determines the next allocated element in the direction 'dir' at the row or + column number 'pos'. The starting point is the element 'current'. */ +/* If called within a loop, the function will give the right result if + the matrix chains are not modified between calls. */ +/* 'dir' is one of mRIGHT, mLEFT, mUP, mDOWN; pos is the row or column number*/ + + +matrix array2matrix(int** ar, int nr, int nc); +/* Converts array to matrix */ + +matrix vector2matrix(int* v, int nr, int nc); +/* Converts vector to matrix */ + +int** vector2array(int* v, int nr, int nc); +/* Converts vector to array */ + +int** matrix2array(matrix m); +/* Converts a matrix object to an array of integers: result[i][j] = elem(i,j)*/ + +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 + return value is the number of nonzero indices. Further, the indices are + stored in 'answer'. Note that *answer is a pointer to memory allocated + in this function. Memory is always allocated, even if there are no indices. + + 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 */ + +#endif Added: pnheaders/pnexample.c =================================================================== --- pnheaders/pnexample.c (rev 0) +++ pnheaders/pnexample.c 2011-04-02 00:10:24 UTC (rev 245) @@ -0,0 +1,148 @@ +#include"pns.h" + +int main() { + int i; + + /* Declaring pn objects */ + + pns pn_p, pn_s, pn_s2, pn, pn2; + + /* Petri nets can be initialized using the incidence matrix */ + + /* This will be used for the incidence matrix of one pn */ + + int Dp[] = { 1, 1, -1, 1, 0, 0,\ + 0, 0, 1, 0, -1, 0,\ + 0, -1, 1, 0, 0, -1,\ + -1, 0, 0, 0, 1, 0,\ + 0, 0, 0, -1, 0, 1}; + + int mp[] = { 1, 1, 1, 1, 1}; /* The initial marking */ + + /* These will be used for the input and output matrices of another pn */ + + int Is[] = { 0, 1, 0, 0,\ + 0, 0, 1, 0,\ + 0, 0, 0, 1,\ + 1, 0, 0, 0}; + + int Os[] = { 0, 0, 1, 0,\ + 0, 0, 0, 1,\ + 1, 0, 0, 0,\ + 0, 1, 0, 0}; + + int ms[] = {0, 0, 1, 1}; /* The initial marking */ + + struct placelist *plist; + arcs* alist; + char *str; + + /* Here is how the pn objects are created */ + + /* The following creates a pn of 5 places, 6 transitions, incidence + matrix Dp, and initial marking mp */ + pn_p = createpn("pnum tnum D m0", 5, 6, Dp, mp); + + /* Here the input and output matrices are used to initialize the pn */ + pn_s = createpn("pnum tnum I O m0", 4, 4, Is, Os, ms); + + /* This creates a pn object without transition arcs */ + pn = createpn("pnum tnum", 3, 5); + + /* GetMatrixEl and SetMatrixEl can be used to read or write the elements + of a matrix. */ + + /* For instance, arcs could be added by changing the value of the input + and output matrices of the pn */ + + SetMatrixEl(&pn.out, 0, 2, 1); /* add arc from p0 to t2 of weight 1 */ + SetMatrixEl(&pn.out, 0, 4, 1); /* add arc from p0 to t4 of weight 1 */ + SetMatrixEl(&pn.out, 2, 4, 1); /* add arc from p2 to t4 of weight 1 */ + SetMatrixEl(&pn.in, 1, 3, 1); /* add arc from t3 to p1 of weight 1 */ + SetMatrixEl(&pn.in, 1, 0, 2); /* add arc from t0 to p1 of weight 2 */ + + /* For instance, to check whether there is an arc from t1 to p2: */ + i = GetMatrixEl(&pn.in, 2, 1); + if(i) + fprintf(stderr, "\nThe arc (t1, p2) has the weight %d.\n", i); + else + fprintf(stderr, "\nThere is no arc from t1 to p2.\n"); + + /* To display in text format a Petri net object use displaypn */ + + fprintf(stderr, "\n** PN_P *************************************\n"); + displaypn(pn_p, stderr); /* displays pn_p */ + fprintf(stderr, "\n** PN_S *************************************\n"); + displaypn(pn_s, stderr); /* displays pn_s */ + fprintf(stderr, "\n** PN *************************************\n"); + displaypn(pn, stderr); /* displays pn */ + + /* Properties of the pn objects can be set or changed with updatepn */ + + updatepn(&pn, "place_name", 0, "start_p"); + /* The line above associates the name "start_p" with the place 0 */ + + updatepn(&pn, "trans_name", 0, "tr0"); + /* The line above associates the name "tr0" with the transition 0 */ + + updatepn(&pn, "select", 1, "f1"); /*select function 'f1' for place 1*/ + + updatepn(&pn, "segment", 0, "i++;");/*code segment 'i++' for place 0*/ + + /* Text transmitted by means of createpn/updatepn is copied to the + corresponding items of the pns object; thus it should be + deallocated, when applicable. For instance: */ + + str = tcalloc(strlen("f1(i, j);")+1, sizeof(char)); + strcpy(str, "f1(i, j);"); + updatepn(&pn, "segment", 1, str); + /* Now, str may be freed, since its content has been copied */ + free(str); + + /* Flags are set as follows. */ + + updatepn(&pn, "unobservable nondeterministic", 0, 1); + /* marks transition 0 unobservable and place 1 as nondeterministic */ + + updatepn(&pn, "live uncontrollable uncontrollable", 0, 0, 2); + /* The line above sets the "live" and "uncontrollable" flags of + transition 0 and the uncontrollable flag of transition 2 */ + + /* Arcs are added similarly (using createpn or updatepn). Here is + an example. */ + + plist = tmalloc(sizeof(struct placelist)); + plist->place = 1; + plist->next = tmalloc(sizeof(*plist)); + plist->next->place = 2; + plist->next->next = 0; + + alist = tmalloc(sizeof(arcs)); + alist->in_place = 0; + alist->out_places = plist; + alist->condition = tcalloc(strlen("j == i || z == 0.1")+1, sizeof(char)); + strcpy(alist->condition, "j == i || z == 0.1"); + alist->next = 0; + + updatepn(&pn, "arcs", 0, alist); /* arc list associated with transition 0 */ + + /* The line above updates the arc_list item of the pns object as well as the + input & output matrices. */ + + /* Note the absence of the lines of code deallocating alist. The object alist is + placed in the pns object, it is not copied. Thus, alist is deallocated when + the pns object is deallocated with the function deallocpn. */ + + /* To create a copy */ + + pn2 = copypn(&pn); + + /* To deallocate a pn object use deallocpn */ + + deallocpn(&pn_p); + deallocpn(&pn_s); + deallocpn(&pn); + deallocpn(&pn2); + + return 0; +} Added: pnheaders/pns.c =================================================================== --- pnheaders/pns.c (rev 0) +++ pnheaders/pns.c 2011-04-02 00:10:24 UTC (rev 245) @@ -0,0 +1,1760 @@ +/**************************************************************************** +PNS.C +Written in 2008-2010 by M. V. Iordache. +****************************************************************************/ + +#include"pns.h" + + +void d2dd(const matrix* D, matrix* Dm, matrix* Dp) { + int i, j, nr, nc; + mtype x; + + nr = NumberOfRows(*D); + nc = NumberOfColumns(*D); + + if(!D || !Dm || !Dp) { + merror(0, "D2DD: one of the parameters has zero address."); + return; + } + + if(nc <= 0 || nr <= 0) { + merror(0, "D2DD: Wrong dimensions of D: %d x %d", D->nr, D->nc); + return; + } + + if((nr != NumberOfRows(*Dm)) || (nc != NumberOfColumns(*Dm)) || \ + (nr != NumberOfRows(*Dp)) || (nc != NumberOfColumns(*Dp))) { + merror(0, "D2DD: One or more parameters have wrong dimensions"); + return; + } + for(i = 0; i < nr; i++) + for(j = 0; j < nc; j++) { + x = GetMatrixEl(D, i, j); + if(x < 0) + SetMatrixEl(Dm, i, j, -x); + else if(x > 0) + SetMatrixEl(Dp, i, j, x); + } +} + + +pns getpn(matrix* Dm, matrix* Dp, int* Tuc, int* Tuo, int* m0, int* C) { + + matrix mDm, mDp; + pns pn; + + if(!Dm && !Dp) { + merror(0, "GETPN: Both Dm and Dn are zero."); return pn; + } + + if(!Dp) { /* In SPNBOX it is possible to call getpn(D) */ + d2dd(Dm, &mDm, &mDp); + pn = createpn("mDm mDp Tuc Tuo m0 C", mDm, mDp, Tuc, Tuo, m0, C); + DeallocateMatrix(&mDm); + DeallocateMatrix(&mDp); + } + else + return createpn("mDm mDp Tuc Tuo m0 C", Dm, Dp, Tuc, Tuo, m0, C); + + return pn; +} + +void _updatepn(pns* pn, const char *str, va_list param); + + +pns createpn(const char *str, ...) { + pns pn; + va_list param; + char* s; + char opt[] = "zero "; /* to set first the pn to zero */ + + s = tmalloc((1+strlen(str)+strlen(opt))*sizeof(char)); + strcpy(s, opt); + strcat(s, str); + + /* Do the initializations */ + + va_start(param, str); + _updatepn(&pn, s, param); + va_end(param); + + free(s); + + return pn; +} + + +void updatepn(pns* pn, const char *str, ...) { + va_list param; + + va_start(param, str); + _updatepn(pn, str, param); + va_end(param); +} + + +/* Subroutines of _updatepn */ + +void inline allocate_matrices(pns* pn) { + if(!(pn->pnum) || !(pn->tnum)) + return; + if(pn->in.nr !=pn->pnum || pn->in.nc !=pn->tnum)/*if not already allocated*/ + AllocateMatrixType(3, &(pn->in), pn->pnum, pn->tnum); + if(pn->out.nr != pn->pnum || pn->out.nc != pn->tnum) + AllocateMatrixType(3, &(pn->out), pn->pnum, pn->tnum); +} + +void ptNumCheck(pns *pn, int m, int n) { + if(m < 0) + merror(0, "_UPDATEPN: Request for %d places!", m); + if(n < 0) + merror(0, "_UPDATEPN: Request for %d places!", n); + if(!pn->pnum && !pn->tnum) { /* If the pn has not been yet initialized */ + pn->pnum = m; + pn->tnum = n; + allocate_matrices(pn); + } + else { + if (pn->pnum != m) + merror(0, "_UPDATEPN: Request to change from %d to %d the number of places", pn->pnum, m); + if (pn->tnum != n) + merror(0, "_UPDATEPN: Request to change from %d to %d the number of transitions", pn->tnum, n); + } +} + + +void pCheck(pns *pn, char* s) { + int i,j; + char *p; + if(!pn->pnum) { + merror(0,"SETPN: Parameter '%s' requires at least one place",s); + return; + } + if(!pn->p) { /* Allocate t if not already allocated */ + pn->p = tmalloc(sizeof(PlaceInfo)*pn->pnum); + for(i = 0; i < pn->pnum; i++) { + p = (char*)&(pn->p[i]); + for(j = 0; j <= sizeof(PlaceInfo)-sizeof(char); j++) + *(p+j) = 0; + } + } +} + + +void tCheck(pns *pn, char* s) { + int i,j; + char *p; + if(!pn->tnum) { + merror(0,"SETPN: Parameter '%s' requires at least one transition",s); + return; + } + if(!pn->t) { /* Allocate t if not already allocated */ + pn->t = tmalloc(sizeof(TransInfo)*pn->tnum); + for(i = 0; i < pn->tnum; i++) { + p = (char*)&(pn->t[i]); + for(j = 0; j <= sizeof(TransInfo)-sizeof(char); j++) + *(p+j) = 0; + } + } +} + +void dealloc_arcs(arcs *pa) { + arcs *p, *p2; + struct placelist *pl, *pl2; + + if(!pa) + return; + for(p = pa; p; ) { + if(p->condition) + free(p->condition); + for(pl = p->out_places; pl; ) { + pl2 = pl; + pl = pl->next; + free(pl2); + } + p2 = p; + p = p->next; + free(p2); + } +} + +void inclArcs(pns* pn, int t, arcs* p_arc) { + arcs* pa, *p, *padst; + struct placelist* pl; + int i; + + if(!p_arc) { /* Remove all transition arcs of t */ + if(pn->arc_list) + if(pn->arc_list[t]) { + dealloc_arcs(pn->arc_list[t]); + pn->arc_list[t] = 0; + } + MakeZeroColumn(&(pn->out), t); + MakeZeroColumn(&(pn->in), t); + return; + } + if(!pn->arc_list) + pn->arc_list = tcalloc(pn->tnum, sizeof(pn->arc_list[0])); + + /* Next, place arcs in arc_list and update the input & output matrices. */ + + /* The following loop places the arcs in increasing order of the in_place field. */ + + for(pa = p_arc; pa; ) { + if(!pn->arc_list[t]) { + pn->arc_list[t] = pa; + pa = pa->next; + pn->arc_list[t]->next = 0; + continue; + } + if(pa->in_place <= pn->arc_list[t]->in_place) { /* insert at the beginning */ + p = pn->arc_list[t]; + pn->arc_list[t] = pa; + pa = pa->next; + pn->arc_list[t]->next = p; + continue; + } + for(padst = pn->arc_list[t]; padst; padst = padst->next) { + if(padst->next) + if(pa->in_place > padst->next->in_place) + continue; + p = padst->next; /* the line is reached if padst->next == 0 or + pa->in_place <= padst->next->in_place */ + padst->next = pa; + pa = pa->next; + padst->next->next = p; + break; + } + } + + /* Update the input and output matrices */ + + MakeZeroColumn(&(pn->out), t); + MakeZeroColumn(&(pn->in), t); + for(pa = pn->arc_list[t]; pa; pa = pa->next) { + if(pa->in_place >= 0) { /* write to the output matrix */ + i = 1 + GetMatrixEl(&(pn->out), pa->in_place, t); + SetMatrixEl(&(pn->out), pa->in_place, t, i); + } + for(pl = pa->out_places; pl; pl = pl->next) { /* write to the input matrix */ + i = 1 + GetMatrixEl(&(pn->in), pl->place, t); + SetMatrixEl(&(pn->in), pl->place, t, i); + } + } +} + + +void inclString(char*** pstr, int index, char* p, int num) { + if(!num || index >= num || index < 0) + merror(0, "SETPN: Attempt to describe undefined places or transitions"); + if(!*pstr) + *pstr = tcalloc(num, sizeof(**pstr)); + if((*pstr)[index]) { + free((*pstr)[index]); + (*pstr)[index] = 0; + } + if(!p) + p = ""; + if(!strlen(p)) + return; + (*pstr)[index] = tcalloc(strlen(p)+1, sizeof(*p)); + strcpy((*pstr)[index], p); +} + + +void _updatepn(pns* pn, const char *str, va_list param) { + arcs* p_arc; + char *sdest, *p; + int i, count, m, n, **ar, *ip, m0, n0; + matrix d, dm, dp; + + m0 = pn->pnum; + n0 = pn->tnum; + + if(!pn || !str) { + merror(0, "SETPN: First two parameters must be nonzero."); + return; + } + + sdest = tmalloc(sizeof(char)*(strlen(str)+1)); + + for(count = 0; str[count]; count++) { + if(str[count] == ' ' || str[count] == '\t') + continue; + + if(sscanf(str+count, "%s", sdest) < 0) { + merror(0, "SETPN could not scan this input: \"%s\".", str); return; } + + /* Advance count to the next field */ + count++; + for(; str[count] != ' ' && str[count] != '\t' && str[count]; count++); + count--; + + if(!strcmp(sdest,"arcs") || !strcmp(sdest,"arc")) { + i = va_arg(param, int); + p_arc = va_arg(param, arcs*); + inclArcs(pn, i, p_arc); + } + else if(!strcmp(sdest,"D") || !strcmp(sdest,"pD")) { + if(!pn->pnum || !pn->tnum) { + merror(0,"SETPN: The D parameter applies to PNs with at least one place and one transition!"); return; + } + if(!strcmp(sdest,"pD")) { + ar = va_arg(param, int**); + if(!ar) { + merror(0,"SETPN: The option pD = 0 is not implemented"); return; + } + d = array2matrix(ar, pn->pnum, pn->tnum); + } + else { /* the case "D" */ + ip = va_arg(param, int*); + if(!ip) { + merror(0,"SETPN: The option D = 0 is not implemented"); return; + } + d = vector2matrix(ip, pn->pnum, pn->tnum); + } + d2dd(&d, &(pn->out), &(pn->in)); + DeallocateMatrix(&d); + } + else if(!strcmp(sdest,"Dm")|| !strcmp(sdest,"O")|| !strcmp(sdest,"pDm")) { + if(!pn->pnum || !pn->tnum) { + merror(0,"SETPN: The Dm parameter applies to PNs with at least one place and one transition!"); return; + } + if(!strcmp(sdest,"pDm")) { + ar = va_arg(param, int**); + if(!ar) { + merror(0,"SETPN: The option pDm = 0 is not implemented"); return; + } + dm = array2matrix(ar, pn->pnum, pn->tnum); + } + else { + ip = va_arg(param, int*); + if(!ip) { + merror(0,"SETPN: The option Dm = 0 is not implemented"); return; + } + dm = vector2matrix(ip, pn->pnum, pn->tnum); + } + CopyMatrix(&dm, &(pn->out)); + DeallocateMatrix(&dm); + } + else if(!strcmp(sdest,"Dp")|| !strcmp(sdest,"I")|| !strcmp(sdest,"pDp")) { + if(!pn->pnum || !pn->tnum) { + merror(0,"SETPN: The Dp parameter applies to PNs with at least one place and one transition!"); return; + } + if(!strcmp(sdest,"pDp")) { + ar = va_arg(param, int**); + if(!ar) { + merror(0,"SETPN: The option pDp = 0 is not implemented"); return; + } + dp = array2matrix(ar, pn->pnum, pn->tnum); + } + else { + ip = va_arg(param, int*); + if(!ip) { + merror(0,"SETPN: The option Dp = 0 is not implemented"); return; + } + dp = vector2matrix(ip, pn->pnum, pn->tnum); + } + CopyMatrix(&dp, &(pn->in)); + DeallocateMatrix(&dp); + } + else if(!strcmp(sdest,"mD")) { + d = va_arg(param, matrix); + m = NumberOfRows(d); + n = NumberOfColumns(d); + ptNumCheck(pn, m, n); /*If uninitialized, pnum and tnum become m and n.*/ + /* If m and n are nonzero, pn->in,out are allocated if necessary.*/ + d2dd(&d, &(pn->out), &(pn->in)); + } + else if(!strcmp(sdest,"mDm")) { + d = va_arg(param, matrix); + m = NumberOfRows(d); + n = NumberOfColumns(d); + ptNumCheck(pn, m, n); /*If uninitialized, pnum and tnum become m and n*/ + ... [truncated message content] |