pntool-developers Mailing List for A Concurrency Tool Suite (Page 3)
Brought to you by:
compaqdrew,
miordache
You can subscribe to this list here.
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(69) |
Jul
(86) |
Aug
(33) |
Sep
|
Oct
|
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
|
Feb
|
Mar
|
Apr
(3) |
May
(3) |
Jun
(1) |
Jul
(10) |
Aug
(2) |
Sep
(1) |
Oct
|
Nov
|
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
From: <Ste...@us...> - 2009-08-14 08:10:16
|
Revision: 215 http://pntool.svn.sourceforge.net/pntool/?rev=215&view=rev Author: StephenCamp Date: 2009-08-14 08:10:08 +0000 (Fri, 14 Aug 2009) Log Message: ----------- Modified fvpr and avpr so that they can now display with or without the index offset needed sometimes to generate output identical to that produced by Matlab. Corrected some logging errors in dp and changed it so that all indices in the log are shown as if they started at 1 - output should be identical to that of a Matlab run. Modified test routines for fvpr, avpr as appropriate. Modified constant definitions for fvpr, avpr modes in spnbox.h. Modified Paths: -------------- spnbox/avpr.c spnbox/dp.c spnbox/fvpr.c spnbox/spnbox.h spnbox/tests/test-avpr.c spnbox/tests/test-avpr.txt spnbox/tests/test-fvpr.c spnbox/tests/test-fvpr.txt Modified: spnbox/avpr.c =================================================================== --- spnbox/avpr.c 2009-08-14 06:56:54 UTC (rev 214) +++ spnbox/avpr.c 2009-08-14 08:10:08 UTC (rev 215) @@ -18,7 +18,7 @@ { char element[64]; - if (mode == DISPLAY_MATRIX) length = MatrixLength(*((matrix*) vector)); + if (mode & DISPLAY_MATRIX) length = MatrixLength(*((matrix*) vector)); /*Fill in default parameters.*/ if (! CheckParams(vector, length, mode, &chr)) return 0; @@ -61,15 +61,15 @@ { if (c == 1) { - sprintf(element, "%s%s%d%s", chr, bl, i + 1, el); + sprintf(element, "%s%s%d%s", chr, bl, i + ((mode & DISPLAY_OFFSET) ? 1 : 0), el); } else if (c == -1) { - sprintf(element, "-%s%s%d%s", chr, bl, i + 1, el); + sprintf(element, "-%s%s%d%s", chr, bl, i + ((mode & DISPLAY_OFFSET) ? 1 : 0), el); } else { - sprintf(element, "%d%s%s%d%s", c, chr, bl, i + 1, el); + sprintf(element, "%d%s%s%d%s", c, chr, bl, i + ((mode & DISPLAY_OFFSET) ? 1 : 0), el); } firstProcessed = 1; } @@ -77,19 +77,19 @@ { if (c == 1) { - sprintf(element, "+%s%s%d%s", chr, bl, i + 1, el); + sprintf(element, "+%s%s%d%s", chr, bl, i + ((mode & DISPLAY_OFFSET) ? 1 : 0), el); } else if (c > 0) { - sprintf(element, "+%d%s%s%d%s", c, chr, bl, i + 1, el); + sprintf(element, "+%d%s%s%d%s", c, chr, bl, i + ((mode & DISPLAY_OFFSET) ? 1 : 0), el); } else if (c == -1) { - sprintf(element, "-%s%s%d%s", chr, bl, i + 1, el); + sprintf(element, "-%s%s%d%s", chr, bl, i + ((mode & DISPLAY_OFFSET) ? 1 : 0), el); } else { - sprintf(element, "%d%s%s%d%s", c, chr, bl, i + 1, el); + sprintf(element, "%d%s%s%d%s", c, chr, bl, i + ((mode & DISPLAY_OFFSET) ? 1 : 0), el); } } strcat(buffer, element); @@ -143,14 +143,13 @@ int GetVectorEl(void* vector, int i, int mode) { - switch(mode) + if (mode & DISPLAY_MATRIX) { - case DISPLAY_MATRIX: return GetMatrixEl((matrix*) vector, i % NumberOfRows(* ((matrix*) vector)), i / NumberOfRows(* ((matrix*) vector))); - break; - case DISPLAY_INTS: + } + else + { return ((int*)vector)[i]; - break; } } @@ -173,10 +172,5 @@ { *chr = "m"; } - if (mode != DISPLAY_MATRIX && mode !=DISPLAY_INTS) - { - merror(0, "AVPR: Invalid mode"); - return 0; - } return 1; } Modified: spnbox/dp.c =================================================================== --- spnbox/dp.c 2009-08-14 06:56:54 UTC (rev 214) +++ spnbox/dp.c 2009-08-14 08:10:08 UTC (rev 215) @@ -404,12 +404,12 @@ achieve = "deadlock-free"; if (d->state.anetfail) { - fprintf(d->log, "in the subsystem containing the transitions\nT = %s", ListTransitions(d->TA, d->TACount)); + fprintf(d->log, " in the subsystem containing the transitions\nT = %s", ListTransitions(d->TA, d->TACount)); fprintf(d->log, "The supervisor may not enforce T-liveness.\n"); } else { - fprintf(d->log, "the supervisor may not enforce liveness.\n"); + fprintf(d->log, ".\nThe supervisor may not enforce liveness.\n"); } } } @@ -491,7 +491,7 @@ } if (d->state.noTlive) { - fprintf(d->log, "No T-livenss enforcing supervisor exists."); + fprintf(d->log, "\nNo T-livenss enforcing supervisor exists."); } } else if (failed) @@ -520,7 +520,7 @@ if (! (NumberOfRows(d->L) && NumberOfRows(d->L0))) { - fprintf(d->log, "\nNo constraints are needed: the Petri net is %s for all initial\nmarkings", supname); + fprintf(d->log, "\nNo constraints are needed: the Petri net is %s for all initial\nmarkings.", supname); } else { @@ -561,7 +561,7 @@ for (i = 0; i < NumberOfRows(*L); i++) { CopyBlock(1, NumberOfColumns(*L), L, i, 0, &lrow, 0, 0); - fprintf(log, "\n%s >= %d", avpr(&lrow, 0, DISPLAY_MATRIX, "m", 0), B[i]); + fprintf(log, "\n%s >= %d", avpr(&lrow, 0, DISPLAY_MATRIX | DISPLAY_OFFSET, "m", 0), B[i]); } fflush(log); DeallocateMatrix(&lrow); @@ -594,7 +594,7 @@ strcpy(buffer, "{"); for (i = 0; i < listCount - 1; i++) { - sprintf(element, "t%d, ", list[i]); + sprintf(element, "t%d, ", list[i] + 1); strcat(buffer, element); } if (listCount) @@ -1198,8 +1198,8 @@ { case 0: /*Display.*/ - fprintf(d->log, "\nNo control places needed. Constraints below added to (L0, B0)"); - fprintf(d->log, "\n%s >= %d", avpr(l, NumberOfColumns(*l), DISPLAY_MATRIX, 0, 0), b); + fprintf(d->log, "\nNo control places needed. Constraints below added to (L0, B0):"); + fprintf(d->log, "\n%s >= %d", avpr(l, NumberOfColumns(*l), DISPLAY_MATRIX | DISPLAY_OFFSET, 0, 0), b); break; case -1: fprintf(d->log, "\nNo constraints added."); @@ -1209,7 +1209,7 @@ break; default: fprintf(d->log, "\nPlace %d added to control the siphon and enforce:", cpl); - fprintf(d->log, "\n%s >= %d", avpr(l, NumberOfColumns(*l), DISPLAY_MATRIX, 0, 0), b); + fprintf(d->log, "\n%s >= %d", avpr(l, NumberOfColumns(*l), DISPLAY_MATRIX | DISPLAY_OFFSET, 0, 0), b); break; } if (wn == 1) fprintf(d->log, "\nSiphon control failure occurred."); @@ -1480,7 +1480,7 @@ void PrintState(dpData *d) { fprintf(d->log, "\nThe Petri net has %d places and %d transitions", NumberOfRows(d->Dm), NumberOfColumns(d->Dm)); - if (d->ExcludeT) fprintf(d->log, "\nThe current active subnet excludes the transitions %s", fvpr(d->ExcludeT, d->ExcludeCount, DISPLAY_INTS, 2)); + if (d->ExcludeT) fprintf(d->log, "\nThe current active subnet excludes the transitions %s", fvpr(d->ExcludeT, d->ExcludeCount, DISPLAY_INTS | DISPLAY_OFFSET, 2)); int i, j; /*Build a list of the original places for vector display.*/ @@ -1492,7 +1492,7 @@ originalPlaces[i] = i; } /*Display it.*/ - fprintf(d->log, "\n %d original places: %s", d->targetRows, fvpr(originalPlaces, d->targetRows, DISPLAY_INTS, 2)); + fprintf(d->log, "\n %d original places: %s", d->targetRows, fvpr(originalPlaces, d->targetRows, DISPLAY_INTS | DISPLAY_OFFSET, 2)); free(originalPlaces); } @@ -1520,22 +1520,22 @@ { if (d->ipCount - firstNewInd == 1) { - fprintf(d->log, "\n One split place: %s", fvpr(d->ipl + firstNewInd, d->ipCount - firstNewInd, DISPLAY_INTS, 2)); + fprintf(d->log, "\n One split place: %s", fvpr(d->ipl + firstNewInd, d->ipCount - firstNewInd, DISPLAY_INTS | DISPLAY_OFFSET, 2)); } else if (d->ipCount - firstNewInd > 1) { - fprintf(d->log, "\n %d split places: %s", d->ipCount - firstNewInd, fvpr(d->ipl + firstNewInd, d->ipCount - firstNewInd, DISPLAY_INTS, 2)); + fprintf(d->log, "\n %d split places: %s", d->ipCount - firstNewInd, fvpr(d->ipl + firstNewInd, d->ipCount - firstNewInd, DISPLAY_INTS | DISPLAY_OFFSET, 2)); } } if (firstNewDep != -1) { if (d->dpCount - firstNewDep == 1) { - fprintf(d->log, "\n One control place: %s", fvpr(d->dpl + firstNewDep, d->dpCount - firstNewDep, DISPLAY_INTS, 2)); + fprintf(d->log, "\n One control place: %s", fvpr(d->dpl + firstNewDep, d->dpCount - firstNewDep, DISPLAY_INTS | DISPLAY_OFFSET, 2)); } else if (d->dpCount - firstNewDep > 1) { - fprintf(d->log, "\n %d control places: %s", d->dpCount - firstNewDep, fvpr(d->dpl + firstNewDep, d->dpCount - firstNewDep, DISPLAY_INTS, 2)); + fprintf(d->log, "\n %d control places: %s", d->dpCount - firstNewDep, fvpr(d->dpl + firstNewDep, d->dpCount - firstNewDep, DISPLAY_INTS | DISPLAY_OFFSET, 2)); } } fprintf(d->log, "\n"); @@ -1552,7 +1552,7 @@ MRow[d->ipl[j]] = GetMatrixEl(&d->M, i, j); } /*Display the row.*/ - fprintf(d->log, "\n %d --> %s >= %d", d->dpl[i], avpr(MRow, NumberOfRows(d->Dm), DISPLAY_INTS, 0, 0), d->G[i]); + fprintf(d->log, "\n %d --> %s >= %d", d->dpl[i], avpr(MRow, NumberOfRows(d->Dm), DISPLAY_INTS | DISPLAY_OFFSET, 0, 0), d->G[i]); } free(MRow); Modified: spnbox/fvpr.c =================================================================== --- spnbox/fvpr.c 2009-08-14 06:56:54 UTC (rev 214) +++ spnbox/fvpr.c 2009-08-14 08:10:08 UTC (rev 215) @@ -18,7 +18,7 @@ char element[64]; /*If the vector is a matrix, get the length.*/ - if (mode == DISPLAY_MATRIX) length = MatrixLength(*((matrix*)vector)); + if (mode & DISPLAY_MATRIX) length = MatrixLength(*((matrix*)vector)); /*Check the parameters.*/ if (! CheckParams(vector, length, mode, option)) return 0; @@ -70,7 +70,7 @@ strcat(buffer, element); } strcat(buffer, cl); - if (mode == DISPLAY_MATRIX && NumberOfRows(*((matrix*)vector)) > 1) + if ((mode & DISPLAY_MATRIX) && NumberOfRows(*((matrix*)vector)) > 1) { strcat(buffer, "'"); } @@ -101,20 +101,19 @@ digits++; } - return strlen(op) + strlen(cl) + ((strlen(", ") + digits) * length) + 1 + ((mode == DISPLAY_MATRIX) ? 1 : 0); + return strlen(op) + strlen(cl) + ((strlen(", ") + digits) * length) + 1 + ((mode & DISPLAY_MATRIX) ? 1 : 0); } int GetVectorEl(void* vector, int i, int mode) { - switch(mode) + if (mode & DISPLAY_MATRIX) { - case DISPLAY_MATRIX: - return GetMatrixEl((matrix*) vector, i % NumberOfRows(* ((matrix*) vector)), i / NumberOfRows(* ((matrix*) vector))); - break; - case DISPLAY_INTS: - return ((int*)vector)[i]; - break; + return GetMatrixEl((matrix*) vector, i % NumberOfRows(* ((matrix*) vector)), i / NumberOfRows(* ((matrix*) vector))) + ((mode & DISPLAY_OFFSET) ? 1 : 0); } + else + { + return ((int*)vector)[i] + ((mode & DISPLAY_OFFSET) ? 1 : 0); + } } int CheckParams(void* vector, int length, int mode, int option) @@ -132,11 +131,6 @@ return 0; } /*If the chr is 0, fill it with the default, m.*/ - if (mode != DISPLAY_MATRIX && mode !=DISPLAY_INTS) - { - merror(0, "FVPR: Invalid mode"); - return 0; - } if (option < 0 || option > 2) { merror(0, "FVPR: Invalid option"); Modified: spnbox/spnbox.h =================================================================== --- spnbox/spnbox.h 2009-08-14 06:56:54 UTC (rev 214) +++ spnbox/spnbox.h 2009-08-14 08:10:08 UTC (rev 215) @@ -244,8 +244,9 @@ #define VRB_MAX 10 /*Constants used to change the behavior of the vector display functions.*/ -#define DISPLAY_MATRIX 0 -#define DISPLAY_INTS 1 +#define DISPLAY_INTS 0 +#define DISPLAY_MATRIX 1 +#define DISPLAY_OFFSET 2 /*Options for dp.*/ #define DP_OPT_WRITELOG 4 @@ -978,6 +979,9 @@ If chr is a null pointer it will default to m, as in Matlab. Use mode = DISPLAY_MATRIX for vector a pointer to a matrix. length is ignored. Use mode = DISPLAY_INTS for vector a pointer to an array of integers. +Or the DISPLAY_OFFSET flag with the DISPLAY_MATRIX or DISPLAY_INTS to build a +string that displays vector indices as if they began at 1 rather than zero. This +will produce the same output as Matlab. The function returns a pointer to a static buffer that it owns. This buffer is overwritten every time the function is called. The caller should use or copy the buffer immediately after calling the function.*/ @@ -996,6 +1000,10 @@ C Usage: Parameters have the same meaning and names as in Matlab. Use mode = DISPLAY_MATRIX for vector a pointer to a matrix. length is ignored. Use mode = DISPLAY_INTS for vector a pointer to an array of integers. +Or the DISPLAY_OFFSET flag with the DISPLAY_MATRIX or DISPLAY_INTS to add 1 to +each value before displaying it. When fvpr is used to display vectors +containing lists of indices, this will effectively shift all the indices up +by one, displaying them as if they began at 1 rather than at 0. This will generate the same output as Matlab when used in these circumstances. The function returns a pointer to a static buffer that it owns. This buffer is overwritten every time the function is called. The caller should use or copy the buffer immediately after calling the function.*/ Modified: spnbox/tests/test-avpr.c =================================================================== --- spnbox/tests/test-avpr.c 2009-08-14 06:56:54 UTC (rev 214) +++ spnbox/tests/test-avpr.c 2009-08-14 08:10:08 UTC (rev 215) @@ -2,8 +2,9 @@ int main(int argc, char* argv[]) { - char iDesc[] = "arrayi V, matrix M, string chr, int option"; + char iDesc[] = "arrayi V, matrix M, string chr, int option, string ShowOffset"; char *result; + char ShowOffset[128] = ""; int* vector = 0; int vLength = 0, option = 0; char chr[128] = ""; @@ -19,18 +20,26 @@ MemoryManager mem = CreateMemoryManager(3, 1, 0, 0); - while (ParseStructure(file, iDesc, &iFill, &mem, &vector, &vLength, &M, chr, &option)) + while (ParseStructure(file, iDesc, &iFill, &mem, &vector, &vLength, &M, chr, &option, ShowOffset)) { if (iFill[0]) iFill[1] = 0; - DisplayStructure(iDesc, iFill, vector, vLength, &M, chr, option); - + DisplayStructure(iDesc, iFill, vector, vLength, &M, chr, option, ShowOffset); + if (iFill[4]) + { + if (strcmp(ShowOffset, "on") && strcmp(ShowOffset, "off")) + { + printf("Warning: Invalid ShowOffset option: '%s'.\n", ShowOffset); + printf("Ignoring. Default is ShowOffset = off.\n"); + ShowOffset[0] = '\0'; + } + } if (iFill[0]) { - result = avpr(vector, vLength, DISPLAY_INTS, chr, option); + result = avpr(vector, vLength, DISPLAY_INTS | (strcmp(ShowOffset, "on") ? 0 : DISPLAY_OFFSET), chr, option); } else if (iFill[1]) { - result = avpr(&M, 0, DISPLAY_MATRIX, chr, option); + result = avpr(&M, 0, DISPLAY_MATRIX | (strcmp(ShowOffset, "on") ? 0 : DISPLAY_OFFSET), chr, option); } else { @@ -46,6 +55,7 @@ vLength = 0; option = 0; chr[0] = '\0'; + ShowOffset[0] = '\0'; printf("-------------------------------------------------------------------------------\n"); } return 1; Modified: spnbox/tests/test-avpr.txt =================================================================== --- spnbox/tests/test-avpr.txt 2009-08-14 06:56:54 UTC (rev 214) +++ spnbox/tests/test-avpr.txt 2009-08-14 08:10:08 UTC (rev 215) @@ -7,42 +7,42 @@ echo Problem 2. echo Solution should be: -echo m1 +echo m0 V 1 1 done echo Problem 3. echo Solution should be: -echo -m1 +echo -m0 V 1 -1 done echo Problem 4. echo Solution should be: -echo 2m1 +echo 2m0 V 1 2 done echo Problem 5 echo Solution should be: -echo -2m1 +echo -2m0 V 1 -2 done echo Problem 6 echo Solution should be: -echo -2m1-m2+m4+2m5 +echo -2m0-m1+m3+2m4 V 5 -2 -1 0 1 2 done echo Problem 7 echo Solution should be: -echo -2z1-z2+z4+2z5 +echo -2z0-z1+z3+2z4 V 5 -2 -1 0 1 2 chr z @@ -50,7 +50,7 @@ echo Problem 8 echo Solution should be: -echo -2m_{1}-m_{2}+m_{4}+2m_{5} +echo -2m_{0}-m_{1}+m_{3}+2m_{4} V 5 -2 -1 0 1 2 option 1 @@ -58,12 +58,23 @@ echo Problem 9 echo Solution should be: +echo -2m_{0}-m_{1}+m_{3}+2m_{4} +M 3 2 +-2 1 +-1 2 + 0 0 +option 1 +done + +echo Problem 10 +echo Solution should be: echo -2m_{1}-m_{2}+m_{4}+2m_{5} M 3 2 -2 1 -1 2 0 0 option 1 +ShowOffset on done quit Modified: spnbox/tests/test-fvpr.c =================================================================== --- spnbox/tests/test-fvpr.c 2009-08-14 06:56:54 UTC (rev 214) +++ spnbox/tests/test-fvpr.c 2009-08-14 08:10:08 UTC (rev 215) @@ -2,12 +2,13 @@ int main(int argc, char* argv[]) { - char iDesc[] = "arrayi V, matrix M, int option"; + char iDesc[] = "arrayi V, matrix M, int option, string ShowOffset"; char *result; int* vector = 0; int vLength = 0; int option = 1; int *iFill; + char ShowOffset[128] = ""; matrix M; FILE* file; @@ -19,18 +20,27 @@ MemoryManager mem = CreateMemoryManager(3, 1, 0, 0); - while (ParseStructure(file, iDesc, &iFill, &mem, &vector, &vLength, &M, &option)) + while (ParseStructure(file, iDesc, &iFill, &mem, &vector, &vLength, &M, &option, ShowOffset)) { if (iFill[0]) iFill[1] = 0; - DisplayStructure(iDesc, iFill, vector, vLength, &M, option); + DisplayStructure(iDesc, iFill, vector, vLength, &M, option, ShowOffset); + if (iFill[3]) + { + if (strcmp(ShowOffset, "on") && strcmp(ShowOffset, "off")) + { + printf("Warning: Invalid ShowOffset option: '%s'.\n", ShowOffset); + printf("Ignoring. Default is ShowOffset = off.\n"); + ShowOffset[0] = '\0'; + } + } if (iFill[0]) { - result = fvpr(vector, vLength, DISPLAY_INTS, option); + result = fvpr(vector, vLength, DISPLAY_INTS | (strcmp(ShowOffset, "on") ? 0 : DISPLAY_OFFSET), option); } else if (iFill[1]) { - result = fvpr(&M, 0, DISPLAY_MATRIX, option); + result = fvpr(&M, 0, DISPLAY_MATRIX | (strcmp(ShowOffset, "on") ? 0 : DISPLAY_OFFSET), option); } else { @@ -45,6 +55,7 @@ vector = 0; vLength = 0; option = 1; + ShowOffset[0] = '\0'; printf("-------------------------------------------------------------------------------\n"); } Modified: spnbox/tests/test-fvpr.txt =================================================================== --- spnbox/tests/test-fvpr.txt 2009-08-14 06:56:54 UTC (rev 214) +++ spnbox/tests/test-fvpr.txt 2009-08-14 08:10:08 UTC (rev 215) @@ -32,4 +32,14 @@ 1 2 3 4 5 6 option 2 done + +echo Problem 6. +echo Solution should be: +echo {2, 3, 4, 5, 6, 7} +M 1 6 +1 2 3 4 5 6 +option 2 +ShowOffset on +done + quit \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-08-14 06:57:08
|
Revision: 214 http://pntool.svn.sourceforge.net/pntool/?rev=214&view=rev Author: StephenCamp Date: 2009-08-14 06:56:54 +0000 (Fri, 14 Aug 2009) Log Message: ----------- Added the third-party memory debugging routines memwatch to the third-party directory, the test makefiles, the spnbox readme on testing, and the pntool license file. Debugged miscellaneous spnbox files. Dp now appears to pass all tests. Note: Dp output has not yet been unified: some functions display 0-based indices and some display 1-based indices. Note: Dp has not yet had the pn2acpn calls used for testing replaced with the pn2eacpn calls intended for use in the final version. Modified Paths: -------------- LICENSE.txt spnbox/README.txt spnbox/admcon.c spnbox/asiph.c spnbox/dp.c spnbox/pn2acpn.c spnbox/spnbox.h spnbox/tests/Makefile spnbox/tests/test-dp.c spnbox/tests/test-dp.txt Added Paths: ----------- third-party/memwatch-2.71/ third-party/memwatch-2.71/FAQ third-party/memwatch-2.71/Makefile third-party/memwatch-2.71/README third-party/memwatch-2.71/USING third-party/memwatch-2.71/gpl.txt third-party/memwatch-2.71/memwatch.c third-party/memwatch-2.71/memwatch.h third-party/memwatch-2.71/memwatch.lsm third-party/memwatch-2.71/test.c Modified: LICENSE.txt =================================================================== --- LICENSE.txt 2009-08-07 06:29:10 UTC (rev 213) +++ LICENSE.txt 2009-08-14 06:56:54 UTC (rev 214) @@ -1,4 +1,5 @@ MILP solver released under the LGPL. (C) Respective authors. +MEMWATCH released under the GPL. (C) Respective authors. ANTLR released under the BSD License. (C) Respective authors. ACTS Copyright (c) 2009 LeTourneau University and University of Notre Dame Modified: spnbox/README.txt =================================================================== --- spnbox/README.txt 2009-08-07 06:29:10 UTC (rev 213) +++ spnbox/README.txt 2009-08-14 06:56:54 UTC (rev 214) @@ -13,7 +13,7 @@ This will generate an executable called <functionname>.exe. make all will generate test executables for all spnbox functions. To test the various functions in the matrixmath.c file, use make matrixmath. To test the functions in the extendedmatrix.c file, use make extendedmatrix. - +The test makefile includes in each source file it compiles the header files and definitions needed to use the memory debugging routines in the memwatch third-party library. (see pntool/third-party/memwatch-2.71). It also compiles and links the file memwatch.c from the library in all test executables. For all with such test programs except that ipslv, the test program is implemented as a program that will read from an input stream containing text in a human-readable format, interpret the text as parameters to the function, make a function call, and display the results. For format specifications, see the comments in StructuredIO.c/h. The programs may be invoked with a single command line argument, which will be taken as the name of a text file from which to read the input. If no command line argument is used the test programs will take input from the console. Modified: spnbox/admcon.c =================================================================== --- spnbox/admcon.c 2009-08-07 06:29:10 UTC (rev 213) +++ spnbox/admcon.c 2009-08-14 06:56:54 UTC (rev 214) @@ -219,7 +219,7 @@ /*During our iterations we will modify a flag array, cov, with an element for each of the columns that came from DX. Allocate space.*/ - int *cov = mcalloc(&mem, placeCount, sizeof(short)); + int *cov = mcalloc(&mem, placeCount, sizeof(int)); /*Start the iterations. Store in j the index of the last column of L such that its element in the last row was set to 1 within the loop. -1 means no column @@ -325,7 +325,7 @@ AllocateMatrixType(2, &DX, p->TucCount + p->TuoCount + p->TuoCount + p->ntCount + 1, NumberOfRows(*Z)); int i, j, k; - for (i = 0; i < NumberOfRows(DX); i++) + for (i = 0; i < NumberOfColumns(DX); i++) { /*Fill in Auc.*/ for (j = 0; j < p->TucCount; j++) Modified: spnbox/asiph.c =================================================================== --- spnbox/asiph.c 2009-08-07 06:29:10 UTC (rev 213) +++ spnbox/asiph.c 2009-08-14 06:56:54 UTC (rev 214) @@ -537,8 +537,8 @@ /*We are going to iterate through the columns of sx. Each column is an active siphon. For each siphon, we determine if there are any transitions such that they have at least one input arc to a place in the siphon but no output arcs - from any places in the siphon. If there are, we modify NS (in result). If not, - we modify MNS (in result) and newIndex.*/ + from any places in the siphon. If there are, we modify NS. If not, we modify + MNS and newIndex.*/ int siphon, place, transition, iFlag, oFlag; for (siphon = 0; siphon < NumberOfColumns(*sx); siphon++) { @@ -578,7 +578,7 @@ int *removeMNSRow = tcalloc(NumberOfRows(data->MNS), sizeof(int)); int removeCount = 0; /*Iterate through each row of MNS*/ - int i, j, flag = 1; + int i, j, k, flag = 1; for (i = 0; i < NumberOfRows(data->MNS); i++) { /*Take the difference MNS - vector. Fill sumDeltas with the sum of the @@ -622,16 +622,20 @@ int* newIndex = tcalloc(NumberOfRows(data->MNS) - removeCount + flag, sizeof(int)); /*Fill in the new index and remove rows from MNS.*/ - j = 0; - for (i = 0; i < NumberOfRows(data->MNS); i++) + j = NumberOfRows(data->MNS) - removeCount; + /*if (! mwIsSafeAddr(index, NumberOfRows(data->MNS) * sizeof(int))) { + merror(0, "BAD MEMORY!"); + }*/ + for (i = NumberOfRows(data->MNS) - 1; i >= 0; i--) + { if (removeMNSRow[i]) { RemoveRows(&data->MNS, i, 1, -1); } else { - newIndex[j++] = index[i]; + newIndex[--j] = index[i]; } } /*Fill in the last element of index and the last row of MNS if necessary.*/ Modified: spnbox/dp.c =================================================================== --- spnbox/dp.c 2009-08-07 06:29:10 UTC (rev 213) +++ spnbox/dp.c 2009-08-14 06:56:54 UTC (rev 214) @@ -69,6 +69,7 @@ int uci, upd, consis; //flags matrix TSIPH; //All siphons found during a run. matrix S; //New siphons found during a run. + int ID; } dpData; /*A set of marking constraints. The return type of UpdateMarkingConstraints, @@ -110,7 +111,7 @@ static void FinalPrint(dpData* d); static void FreeDpParts(dpData* d); -dp_r dp(dp_p* params) +dp_r dp(dp_p* params, int ID) { dp_r result; int i, j, flag; @@ -123,7 +124,7 @@ /*Initialize the data structure.*/ dpData d = CreateDpData(params); - + d.ID = ID; /*Initial message printing.*/ if (is_verbose() >= VRB_DP) { @@ -133,7 +134,7 @@ printf("Producing a deadlock prevention supervisor...\n"); break; case 1: - printf("Produceing a liveness enforcing supervisor...\n"); + printf("Producing a liveness enforcing supervisor...\n"); break; case 2: printf("Producing a T-liveness enforcing supervisor...\n"); @@ -745,7 +746,14 @@ /*Check the constraints if applicable.*/ if (d->consis) { - chkconsRes = chkcons(&cons.L, cons.B, &l, b); + /*We are checking constraints for consistency, not redundancy - add + the proposed new constraint to the set of constraints. Use a copy + so that the memory can be absorbed into L in an optimized operation.*/ + AddToArray(&cons.B, NumberOfRows(cons.L), b); + AllocateMatrixType(2, &l2, 1, NumberOfColumns(l)); + CopyMatrix(&l, &l2); + InsertRows(&cons.L, &l2, -1, -1); + chkconsRes = chkcons(&cons.L, cons.B, 0, 0); } else { @@ -758,9 +766,9 @@ x = 0; for (i = 0; i < NumberOfRows(d->S); i++) { - if ((! GetMatrixEl(&d->S, i, siphon)) != (! GetMatrixEl(&a, i, 0))) + if ((! GetMatrixEl(&d->S, i, siphon)) != (! GetMatrixEl(&a, 0, i))) { - /*If such a place is encounted, set the generic variable x to 2 for + /*If such a place is encountered, set the generic variable x to 2 for later use as a function parameter.*/ x = 2; break; @@ -785,7 +793,7 @@ AddToIndexArray(&d->upl, &d->upCount, NumberOfRows(supervisRes.Dfm) - 1); AddToIndexArray(&d->cpl, &d->cpCount, NumberOfRows(supervisRes.Dfm) - 1); /*Dm and Dp should be set to the supervised net Dfm and Dfp.*/ - UpdateDPData(d, "Dm Dp", &supervisRes); + UpdateDPData(d, "Dm Dp", &supervisRes); memset(&supervisRes, 0, sizeof(supervis_r)); /*Add to the constraints. Make a copy of l first so that we can do optimized row-adds and not do too many allocations.*/ @@ -807,7 +815,7 @@ { /*Add the built constraint to the initial marking constraints.*/ if (d->log) PrintConstraints(d, &l, b, currentSiphon, 0, x); - AddToArray(&d->B0, NumberOfRows(d->L0), NumberOfRows(d->L0)); + AddToArray(&d->B0, NumberOfRows(d->L0), b); InsertRows(&d->L0, &l, -1, -1); } } @@ -843,7 +851,12 @@ else { if (d->log) PrintConstraints(d, 0, 0, currentSiphon, -1, 0); - } + } + if (NumberOfRows(cons.L)) + { + DeallocateMatrix(&cons.L); + free(cons.B); + } } } @@ -1229,10 +1242,10 @@ { if (GetMatrixEl(&d->Dcm, i, j) || GetMatrixEl(&d->Dcp, i, j)) { + newApl[d->apCount++] = i; break; } } - if (j != NumberOfColumns(d->Dcm)) newApl[d->apCount++] = i; } free(d->apl); d->apl = newApl; @@ -1489,7 +1502,7 @@ int firstNewInd = -1, firstNewDep = -1; for (i = 0; i < d->ipCount; i++) { - if (d->ipl[i] > d->targetRows) + if (d->ipl[i] >= d->targetRows) { firstNewInd = i; break; @@ -1497,7 +1510,7 @@ } for (i = 0; i < d->dpCount; i++) { - if (d->dpl[i] > d->targetRows) + if (d->dpl[i] >= d->targetRows) { firstNewDep = i; break; @@ -1663,7 +1676,7 @@ is too high and marking this as the list length.*/ for (i = 0; i < d->ExcludeCount; i++) { - if (d->ExcludeT[i] > d->targetCols) break; + if (d->ExcludeT[i] >= d->targetCols) break; } d->ExcludeCount = i; d->state.perm = 1; @@ -1926,7 +1939,10 @@ else if (! strcmp(token, "Dcm")) destMatrix = &data->Dcm; else if (! strcmp(token, "Dcp")) destMatrix = &data->Dcp; else if (! strcmp(token, "L")) destMatrix = &data->L; - else if (! strcmp(token, "L0")) destMatrix = &data->L0; + else if (! strcmp(token, "L0")) + { + destMatrix = &data->L0; + } else if (! strcmp(token, "M")) destMatrix = &data->M; else if (! strcmp(token, "TSIPH")) destMatrix = &data->TSIPH; else if (! strcmp(token, "S")) destMatrix = &data->S; Modified: spnbox/pn2acpn.c =================================================================== --- spnbox/pn2acpn.c 2009-08-07 06:29:10 UTC (rev 213) +++ spnbox/pn2acpn.c 2009-08-14 06:56:54 UTC (rev 214) @@ -161,8 +161,8 @@ /*We will be adding new columns to MX and L0. Reseve space and copy existing columns.*/ - if (NumberOfRows(result->MXF)) - { + if (result->MXF.type) + { AllocateMatrixType(2, &MX, NumberOfRows(result->MXF), NumberOfColumns(result->MXF) + ToAdd); CopyBlock(NumberOfRows(result->MXF), NumberOfColumns(result->MXF), &result->MXF, 0, 0, &MX, 0, 0); } @@ -171,7 +171,7 @@ /*Zero MX.*/ AllocateMatrix(&MX, 0, 0); } - if (NumberOfRows(result->L0F)) + if (result->L0F.type) { AllocateMatrixType(2, &L0, NumberOfRows(result->L0F), NumberOfColumns(result->L0F) + ToAdd); CopyBlock(NumberOfRows(result->L0F), NumberOfColumns(result->L0F), &result->L0F, 0, 0, &L0, 0, 0); @@ -208,7 +208,7 @@ interest.*/ SetMatrixEl(&Dmf, Rows + j, Transition, GetMatrixEl(Dm, i, Transition)); /*Modify MX and L0 if they exist.*/ - if (NumberOfRows(MX) || NumberOfRows(L0)) + if (NumberOfColumns(MX) || NumberOfColumns(L0)) { /*Find out if the current place is independent..*/ for (x = 0; x < ipCount; x++) @@ -223,11 +223,11 @@ place just found. (if they exist)*/ if (x < ipCount) { - if (NumberOfRows(MX)) + if (NumberOfColumns(MX)) { CopyBlock(NumberOfRows(MX), 1, &MX, 0, x, &MX, 0, NumberOfColumns(MX) - ToAdd + j); } - if (NumberOfRows(L0)) + if (NumberOfColumns(L0)) { CopyBlock(NumberOfRows(L0), 1, &L0, 0, x, &L0, 0, NumberOfColumns(L0) - ToAdd + j); } @@ -244,7 +244,7 @@ if (x < dpCount && NumberOfRows(MX)) { SetMatrixEl(&MX, x, NumberOfColumns(MX) - ToAdd + j, -1); - } + } } } /*Increment the added-place counter.*/ @@ -255,12 +255,12 @@ result->Dmf = Dmf; DeallocateMatrix(&result->Dpf); result->Dpf = Dpf; - if (NumberOfRows(MX)) + if (NumberOfColumns(MX)) { DeallocateMatrix(&result->MXF); result->MXF = MX; } - if (NumberOfRows(L0)) + if (NumberOfColumns(L0)) { DeallocateMatrix(&result->L0F); result->L0F = L0; @@ -386,7 +386,7 @@ arc. If we exceed the matrix boundaries looking for it, fail.*/ while (! GetMatrixEl(&result->Dmf, ++i, Transition)) { - if (i >= NumberOfRows(result->Dmf)) + if (i == NumberOfRows(result->Dmf) - 1) { merror(0, "PN2ACPN: Internal Error"); /*Set U equal to an error value and return it.*/ @@ -407,7 +407,7 @@ arc. If we exceed the matrix boundaries looking for it, fail.*/ while (! GetMatrixEl(&result->Dmf, ++j, Transition)) { - if (j >= NumberOfRows(result->Dmf)) + if (j == NumberOfRows(result->Dmf) - 1) { merror(0, "PN2ACPN: Internal Error"); /*Set U equal to an error value and return it.*/ Modified: spnbox/spnbox.h =================================================================== --- spnbox/spnbox.h 2009-08-07 06:29:10 UTC (rev 213) +++ spnbox/spnbox.h 2009-08-14 06:56:54 UTC (rev 214) @@ -1023,7 +1023,7 @@ int option; } dp_p; -dp_r dp(dp_p* params); +dp_r dp(dp_p* params, int ID); /* Matlab Usage: Modified: spnbox/tests/Makefile =================================================================== --- spnbox/tests/Makefile 2009-08-07 06:29:10 UTC (rev 213) +++ spnbox/tests/Makefile 2009-08-14 06:56:54 UTC (rev 214) @@ -5,9 +5,9 @@ #<functionname> is the name of an spnbox function. This builds the test routines for that function. COMPILER=gcc -g - +MEMWCOMP=$(COMPILER) -include string.h -include ../../third-party/memwatch-2.71/memwatch.h -DMEMWATCH -DMEMWATCH_STDIO #The dependencies common to all test executables. -COMMON=StructuredIO.o test.o MemoryManager.o general.o pns.o matrix.o matrixmath.o deallocation.o +COMMON=StructuredIO.o test.o MemoryManager.o general.o pns.o matrix.o matrixmath.o deallocation.o memwatch.o #These symbols define the dependencies of various test executables. AVPR=avpr.o @@ -83,109 +83,113 @@ #Rules for making the general object files. actn.o: ../actn.c ../spnbox.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../matrixmath.h ../MemoryManager.h - $(COMPILER) -c ../actn.c + $(MEMWCOMP) -c ../actn.c admcon.o: ../admcon.c ../spnbox.h ../matrixmath.h ../extendedmatrix.h ../../pnheaders/general.h ../../pnheaders/matrix.h - $(COMPILER) -c ../admcon.c + $(MEMWCOMP) -c ../admcon.c asiph.o: ../asiph.c ../spnbox.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../extendedmatrix.h ../MemoryManager.h - $(COMPILER) -c ../asiph.c + $(MEMWCOMP) -c ../asiph.c avpr.o: ../avpr.c ../../pnheaders/general.h ../../pnheaders/matrix.h - $(COMPILER) -c ../avpr.c + $(MEMWCOMP) -c ../avpr.c chkcons.o: ../spnbox.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../chkcons.c - $(COMPILER) -c ../chkcons.c + $(MEMWCOMP) -c ../chkcons.c deallocation.o: ../deallocation.c ../spnbox.h - $(COMPILER) -c ../deallocation.c + $(MEMWCOMP) -c ../deallocation.c dp.o: ../dp.c ../spnbox.h ../matrixmath.h ../extendedmatrix.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../../pnheaders/pns.h - $(COMPILER) -c ../dp.c + $(MEMWCOMP) -c ../dp.c extendedmatrix.o: ../extendedmatrix.c ../extendedmatrix.h ../../pnheaders/matrix.h ../../pnheaders/general.h - $(COMPILER) -c ../extendedmatrix.c + $(MEMWCOMP) -c ../extendedmatrix.c fvpr.o: ../fvpr.c ../../pnheaders/general.h ../../pnheaders/matrix.h - $(COMPILER) -c ../fvpr.c + $(MEMWCOMP) -c ../fvpr.c general.o: ../../pnheaders/general.c ../../pnheaders/general.h - $(COMPILER) -c ../../pnheaders/general.c + $(MEMWCOMP) -c ../../pnheaders/general.c ilpadm.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../ilpadm.c - $(COMPILER) -c ../ilpadm.c + $(MEMWCOMP) -c ../ilpadm.c isadm.o: ../isadm.c ../spnbox.h ../../pnheaders/general.h ../MemoryManager.h ../../pnheaders/pns.h ../matrixmath.h - $(COMPILER) -c ../isadm.c + $(MEMWCOMP) -c ../isadm.c issiph.o: ../issiph.c ../spnbox.h ../../pnheaders/general.h ../../pnheaders/matrix.h - $(COMPILER) -c ../issiph.c + $(MEMWCOMP) -c ../issiph.c ipslv.o: ../spnbox.h ../ipslv.c - $(COMPILER) -c ../ipslv.c + $(MEMWCOMP) -c ../ipslv.c ipsolve.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../ipsolve.c - $(COMPILER) -c ../ipsolve.c + $(MEMWCOMP) -c ../ipsolve.c linenf.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../linenf.c - $(COMPILER) -c ../linenf.c + $(MEMWCOMP) -c ../linenf.c matrix.o: ../../pnheaders/matrix.c ../../pnheaders/matrix.h ../../pnheaders/pns.h - $(COMPILER) -c ../../pnheaders/matrix.c + $(MEMWCOMP) -c ../../pnheaders/matrix.c matrixmath.o: ../matrixmath.c ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h - $(COMPILER) -c ../matrixmath.c + $(MEMWCOMP) -c ../matrixmath.c MemoryManager.o: ../MemoryManager.h ../MemoryManager.c ../../pnheaders/general.h ../../pnheaders/matrix.h - $(COMPILER) -c ../MemoryManager.c + $(MEMWCOMP) -c ../MemoryManager.c msplit.o: ../spnbox.h ../../pnheaders/matrix.h ../matrixmath.h ../MemoryManager.h ../msplit.c - $(COMPILER) -c ../msplit.c + $(MEMWCOMP) -c ../msplit.c nltrans.o: ../nltrans.c ../spnbox.h ../../pnheaders/matrix.h ../matrixmath.h ../MemoryManager.h - $(COMPILER) -c ../nltrans.c + $(MEMWCOMP) -c ../nltrans.c pn2acpn.o: ../spnbox.h ../../pnheaders/matrix.h ../MemoryManager.h ../pn2acpn.c - $(COMPILER) -c ../pn2acpn.c + $(MEMWCOMP) -c ../pn2acpn.c pn2eacpn.o: ../spnbox.h ../../pnheaders/matrix.h ../MemoryManager.h ../pn2eacpn.c - $(COMPILER) -c ../pn2eacpn.c + $(MEMWCOMP) -c ../pn2eacpn.c pns.o: ../../pnheaders/pns.c ../../pnheaders/pns.h ../../pnheaders/general.h ../../pnheaders/matrix.h - $(COMPILER) -c ../../pnheaders/pns.c + $(MEMWCOMP) -c ../../pnheaders/pns.c reduce.o: ../spnbox.h ../extendedmatrix.h ../../pnheaders/matrix.h ../reduce.c - $(COMPILER) -c ../reduce.c + $(MEMWCOMP) -c ../reduce.c supervis.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/ ../../pnheaders/matrix.h ../supervis.c ../extendedmatrix.h - $(COMPILER) -c ../supervis.c + $(MEMWCOMP) -c ../supervis.c StructuredIO.o: ../MemoryManager.h ../../pnheaders/matrix.h StructuredIO.h StructuredIO.c - $(COMPILER) -c StructuredIO.c + $(MEMWCOMP) -c StructuredIO.c tactn.o: ../tactn.c ../spnbox.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../matrixmath.h ../MemoryManager.h - $(COMPILER) -c ../tactn.c + $(MEMWCOMP) -c ../tactn.c test.o: test.c test.h ../../pnheaders/pns.h ../../pnheaders/matrix.h ../matrixmath.h ../spnbox.h ../MemoryManager.h StructuredIO.h - $(COMPILER) -c test.c + $(MEMWCOMP) -c test.c #Rules for making the test executable object files. test-actn.o: test-actn.c $(COMMONHEADER) - $(COMPILER) -c test-actn.c + $(MEMWCOMP) -c test-actn.c test-admcon.o: test-admcon.c $(COMMONHEADER) - $(COMPILER) -c test-admcon.c + $(MEMWCOMP) -c test-admcon.c test-asiph.o: test-asiph.c $(COMMONHEADER) - $(COMPILER) -c test-asiph.c + $(MEMWCOMP) -c test-asiph.c test-avpr.o: test-avpr.c $(COMMONHEADER) - $(COMPILER) -c test-avpr.c + $(MEMWCOMP) -c test-avpr.c test-extendedmatrix.o: test-extendedmatrix.c $(COMMONHEADER) - $(COMPILER) -c test-extendedmatrix.c + $(MEMWCOMP) -c test-extendedmatrix.c test-dp.o: test-dp.c $(COMMONHEADER) - $(COMPILER) -c test-dp.c + $(MEMWCOMP) -c test-dp.c test-fvpr.o: test-fvpr.c $(COMMONHEADER) - $(COMPILER) -c test-fvpr.c + $(MEMWCOMP) -c test-fvpr.c test-ilpadm.o: test-ilpadm.c $(COMMONHEADER) - $(COMPILER) -c test-ilpadm.c + $(MEMWCOMP) -c test-ilpadm.c test-ipslv.o: test-ipslv.c - $(COMPILER) -c test-ipslv.c + $(MEMWCOMP) -c test-ipslv.c test-ipsolve.o: test-ipsolve.c $(COMMONHEADER) - $(COMPILER) -c test-ipsolve.c + $(MEMWCOMP) -c test-ipsolve.c test-isadm.o: test-isadm.c $(COMMONHEADER) - $(COMPILER) -c test-isadm.c + $(MEMWCOMP) -c test-isadm.c test-linenf.o: test-linenf.c $(COMMONHEADER) - $(COMPILER) -c test-linenf.c + $(MEMWCOMP) -c test-linenf.c test-matrixmath.o: test-matrixmath.c $(COMMONHEADER) - $(COMPILER) -c test-matrixmath.c + $(MEMWCOMP) -c test-matrixmath.c test-msplit.o: test-msplit.c $(COMMONHEADER) - $(COMPILER) -c test-msplit.c + $(MEMWCOMP) -c test-msplit.c test-nltrans.o: test-nltrans.c $(COMMONHEADER) - $(COMPILER) -c test-nltrans.c + $(MEMWCOMP) -c test-nltrans.c test-pn2acpn.o: test-pn2acpn.c $(COMMONHEADER) - $(COMPILER) -c test-pn2acpn.c + $(MEMWCOMP) -c test-pn2acpn.c test-pn2eacpn.o: test-pn2eacpn.c $(COMMONHEADER) - $(COMPILER) -c test-pn2eacpn.c + $(MEMWCOMP) -c test-pn2eacpn.c test-supervis.o: test-supervis.c $(COMMONHEADER) - $(COMPILER) -c test-supervis.c + $(MEMWCOMP) -c test-supervis.c test-reduce.o: test-reduce.c $(COMMONHEADER) - $(COMPILER) -c test-reduce.c + $(MEMWCOMP) -c test-reduce.c test-tactn.o: test-tactn.c $(COMMONHEADER) - $(COMPILER) -c test-tactn.c + $(MEMWCOMP) -c test-tactn.c #Rules for making the liblpsolve55.a static library for use with ipsolve. ../liblpsolve55.a: ../../third-party/lp_solve_5.5/lpsolve55/liblpsolve55.a cp ../../third-party/lp_solve_5.5/lpsolve55/liblpsolve55.a ../liblpsolve55.a ../../third-party/lp_solve_5.5/lpsolve55/liblpsolve55.a: - cd ../../third-party/lp_solve_5.5; make -f Makefile.linux lib \ No newline at end of file + cd ../../third-party/lp_solve_5.5; make -f Makefile.linux lib + +#The memwatch libraries. +memwatch.o: ../../third-party/memwatch-2.71/memwatch.c ../../third-party/memwatch-2.71/memwatch.h + $(COMPILER) -c ../../third-party/memwatch-2.71/memwatch.c \ No newline at end of file Modified: spnbox/tests/test-dp.c =================================================================== --- spnbox/tests/test-dp.c 2009-08-07 06:29:10 UTC (rev 213) +++ spnbox/tests/test-dp.c 2009-08-14 06:56:54 UTC (rev 214) @@ -7,11 +7,11 @@ { return 0; } - char iDesc[] = "matrix D, matrix Dm, matrix Dp, indexarray Tuc, indexarray Tuo, arrayi IncludeT, arrayi ExcludeT, arrayi B, arrayi B0, matrix L, matrix L0, string WriteLog, string EnforceLive"; + char iDesc[] = "matrix D, matrix Dm, matrix Dp, indexarray Tuc, indexarray Tuo, arrayi IncludeT, arrayi ExcludeT, arrayi B, arrayi B0, matrix L, matrix L0, string WriteLog, string EnforceLive, int ID"; char oDesc[] = "matrix Lf, arrayi Bf, matrix L0f, arrayi B0f, string how"; int *iFill; int oFill[5]; - int BCount, B0Count, i; + int BCount, B0Count, i, ID; matrix D; char WriteLog[128] = "", EnforceLive[128] = ""; dp_p p; @@ -30,10 +30,11 @@ remove("dp.log"); remove("dp.dat"); int transitions; - while (ParseStructure(input, iDesc, &iFill, &mem, &D, &p.Dm, &p.Dp, &p.Tuc, &p.TucCount, &p.Tuo, &p.TuoCount, &p.IncludeT, &p.IncludeCount, &p.ExcludeT, &p.ExcludeCount, &p.B, &BCount, &p.B0, &B0Count, &p.L, &p.L0, WriteLog, EnforceLive)) + ID = -1; + while (ParseStructure(input, iDesc, &iFill, &mem, &D, &p.Dm, &p.Dp, &p.Tuc, &p.TucCount, &p.Tuo, &p.TuoCount, &p.IncludeT, &p.IncludeCount, &p.ExcludeT, &p.ExcludeCount, &p.B, &BCount, &p.B0, &B0Count, &p.L, &p.L0, WriteLog, EnforceLive, &ID)) { transitions = (iFill[0] ? NumberOfColumns(D) : (iFill[1] ? NumberOfColumns(p.Dm) : (iFill[2] ? NumberOfColumns(p.Dp) : 0))); - DisplayStructure(iDesc, iFill, &D, &p.Dm, &p.Dp, p.Tuc, p.TucCount, NumberOfColumns(p.Dm), p.Tuo, p.TuoCount, NumberOfColumns(p.Dm), p.IncludeT, p.IncludeCount, p.ExcludeT, p.ExcludeCount, p.B, BCount, p.B0, B0Count, &p.L, &p.L0, WriteLog, EnforceLive); + DisplayStructure(iDesc, iFill, &D, &p.Dm, &p.Dp, p.Tuc, p.TucCount, NumberOfColumns(p.Dm), p.Tuo, p.TuoCount, NumberOfColumns(p.Dm), p.IncludeT, p.IncludeCount, p.ExcludeT, p.ExcludeCount, p.B, BCount, p.B0, B0Count, &p.L, &p.L0, WriteLog, EnforceLive, ID); FillDmDp(iFill, &D, &p.Dm, &p.Dp, &mem); /*Log writing defaults to on.*/ if (strcmp(WriteLog, "off")) p.option |= DP_OPT_WRITELOG; @@ -53,7 +54,7 @@ //For the duration of a test, append to the log files. p.option |= DP_OPT_APPENDLOGS; - dp_r res = dp(&p); + dp_r res = dp(&p, ID); printf("Solution:\n"); DisplayStructure(oDesc, oFill, &res.Lf, res.Bf, NumberOfRows(res.Lf), &res.L0f, res.B0f, NumberOfRows(res.L0f), res.how); printf("-------------------------------------------------------------------------------\n\n"); @@ -62,6 +63,7 @@ mem = CreateMemoryManager(10, 10, 0, 0); memset(&p, 0, sizeof(dp_p)); + ID = -1; WriteLog[0] = '\0'; EnforceLive[0] = '\0'; } Modified: spnbox/tests/test-dp.txt =================================================================== --- spnbox/tests/test-dp.txt 2009-08-07 06:29:10 UTC (rev 213) +++ spnbox/tests/test-dp.txt 2009-08-14 06:56:54 UTC (rev 214) @@ -2,12 +2,16 @@ rem arrayi IncludeT, arrayi ExcludeT, arrayi B, arrayi B0, matrix L, matrix L0, rem string WriteLog = on/off, string EnforceLive = on/off +echo --------------------------------------------------------------------------- +echo ----- Deadlock Prevention Tests ----- +echo --------------------------------------------------------------------------- echo Deadlock prevention tests. echo Problem 1. echo Example 5.2 from [Iordache, 2000] echo Answer should be: echo L = [ 2 2 1 ] echo b = [ 2 ] +ID 1 Dp 3 5 0 1 0 1 0 0 0 1 0 1 @@ -21,6 +25,7 @@ echo Problem 2. echo A Petri net in which deadlock cannot be prevented. +ID 2 Dp 3 3 0 1 0 0 0 1 @@ -34,6 +39,7 @@ echo Problem 3. echo A repetetive Petri net with no smaller siphons. +ID 3 Dm 3 3 0 1 0 1 0 0 @@ -48,6 +54,7 @@ echo Problem 4. echo A similar net that is not strongly connected, i.e. the union of two echo distinct repetitive Petri nets. +ID 4 Dm 6 6 0 1 0 0 0 0 1 0 0 0 0 0 @@ -74,7 +81,7 @@ echo B = [ 1 ] echo ....[ 1 ] echo ....[ 3 ] - +ID 5 Dm 4 5 1 0 1 0 1 0 0 0 1 0 @@ -94,7 +101,7 @@ echo L = [ 1 1 0 0 ] B = [ 1 ] echo ....[ 0 0 1 1 ] [ 1 ] echo ....[ 1 1 1 1 ] [ 3 ] - +ID 6 Dm 4 5 1 0 1 0 1 0 0 0 1 0 @@ -117,6 +124,7 @@ echo This is an example from K. Lautenback, et al, "The Linear Algebra of echo Deadlock Avoidance - A Petri Net Approach", technical report at the echo University of Koblenz, Institute for Computer Science, 1996. +ID 7 Dm 4 4 3 0 5 0 0 1 0 0 @@ -135,6 +143,7 @@ echo L = [ 2 0 1 ] B = [ 1 ] echo .....[ 0 2 1 ] [ 1 ] echo L0 = [ 2 2 2 ] B0 = [ 3 ] +ID 8 D 3 3 -1 1 0 -1 0 1 @@ -142,4 +151,156 @@ Tuo 1 0 done + +echo --------------------------------------------------------------------------- +echo ----- Liveness Enforcement Tests ----- +echo --------------------------------------------------------------------------- +echo Problem 0. (from dpdem4.m) +ID 100 +D 15 11 +-1 0 0 0 1 0 1 0 0 0 0 + 0 0 0 0 0 1 -1 0 0 0 0 + 0 1 -1 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 1 -1 0 + 0 0 1 -1 0 0 0 0 0 0 0 + 0 0 0 0 -1 0 0 0 0 0 0 + 1 -1 0 0 0 -1 0 0 0 0 0 + 0 0 0 0 0 0 0 1 -1 0 0 + 0 0 0 0 0 0 0 0 0 0 -1 + 0 0 0 0 0 0 0 -1 0 0 1 +-1 1 0 0 0 1 0 0 0 0 0 + 0 -1 1 0 0 0 0 0 0 -1 1 + 0 0 -1 1 0 0 0 0 -1 1 0 + 0 0 0 -1 1 0 0 -1 1 0 0 + 0 0 0 0 0 -1 1 0 0 0 0 +EnforceLive on +done + +echo Problem 1. Example 5.2 from the ISIS report #4 of 2000. +echo The answer should be: +echo L = [ 2 2 1 ] B = [ 2 ] +ID 101 +Dp 3 5 +0 1 0 1 0 +0 0 1 0 1 +1 0 0 0 0 +Dm 3 5 +1 0 0 0 1 +1 0 0 1 0 +0 2 2 0 0 +EnforceLive on +done + +echo Problem 2. A Petri net in which deadlock cannot be prevented. +ID 102 +Dp 3 3 +0 1 0 +0 0 1 +1 0 0 +Dm 3 3 +1 0 0 +1 0 0 +0 1 1 +EnforceLive on +done + +echo Problem 3. A repetitive net. +ID 103 +Dm 3 3 +0 1 0 +1 0 0 +0 0 1 +Dp 3 3 +1 0 0 +0 0 1 +0 1 0 +EnforceLive on +done + +echo Problem 4. The union of two distinct repetetive Petri nets. +ID 104 +Dm 6 6 +0 1 0 0 0 0 +1 0 0 0 0 0 +0 0 1 0 0 0 +0 0 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 1 +Dp 6 6 +1 0 0 0 0 0 +0 0 1 0 0 0 +0 1 0 0 0 0 +0 0 0 1 0 0 +0 0 0 0 0 1 +0 0 0 0 1 0 +EnforceLive on +done + +echo Problem 5. DAta from Example 5.1 from ISIS report #3 of 2000. +ID 105 +Dm 4 5 +1 0 1 0 1 +0 0 0 1 0 +0 1 0 0 1 +1 0 1 0 0 +Dp 4 5 +0 0 0 1 0 +0 0 2 0 1 +3 0 0 0 0 +0 1 0 0 0 +EnforceLive on +done + +echo Problem 6. The same as Problem 5 (Data from Example 5.1 from ISIS report #3 +echo of 2000.) except with an initial constraint. +ID 106 +Dm 4 5 +1 0 1 0 1 +0 0 0 1 0 +0 1 0 0 1 +1 0 1 0 0 +Dp 4 5 +0 0 0 1 0 +0 0 2 0 1 +3 0 0 0 0 +0 1 0 0 0 +L 1 4 +1 1 1 1 +B 1 3 +EnforceLive on +done + +echo Problem 7. Example 5.3 from ISIS report #4 of 2000. +echo Has an unobservable transition. +echo Answer should be: +echo L = [ 2 0 1 ] B = [ 1 ] +echo .....[ 0 2 1 ] [ 1 ] +echo L0 = [ 2 2 2 ] B0 = [ 3 ] +ID 107 +D 3 3 +-1 1 0 +-1 0 1 + 2 -1 -1 +Tuo 1 0 +EnforceLive on +done + +echo Problem 8. Example 5.4 from ISIS report #4 of 2000. +echo Has initial constraints. +echo The right answer should be: +echo L = [ 1 0 1 1 1 ] B = [ 1 ] +echo .....[ 0 1 1 1 1 ] [ 1 ] +echo L0 = [ -1 -1 -1 -1 -1 ] B0 = [ -1 ] +ID 108 +D 5 6 +-1 1 0 0 0 0 +-1 0 1 0 0 0 + 2 -1 -1 -1 0 0 + 0 0 0 1 1 -1 + 0 0 0 0 -1 1 +L0 1 5 +-1 -1 -1 -1 -1 +B0 1 -1 +EnforceLive on +done quit Added: third-party/memwatch-2.71/FAQ =================================================================== --- third-party/memwatch-2.71/FAQ (rev 0) +++ third-party/memwatch-2.71/FAQ 2009-08-14 06:56:54 UTC (rev 214) @@ -0,0 +1,133 @@ +Frequently Asked Questions for memwatch + +Q. I'm not getting any log file! What's wrong?? + +A. Did you define MEMWATCH when compiling all files? + Did you include memwatch.h in all the files? + If you did, then...: + + Memwatch creates the file when it initializes. If you're not + getting the log file, it's because a) memwatch is not + initializing or b) it's initializing, but can't create the + file. + + Memwatch has two functions, mwInit() and mwTerm(), that + initialize and terminate memwatch, respectively. They are + nestable. You USUALLY don't need to call mwInit() and + mwTerm(), since memwatch will auto-initialize on the first + call to a memory function, and then add mwTerm() to the + atexit() list. + + You can call mwInit() and mwTerm() manually, if it's not + initializing properly or if your system doesn't support + atexit(). Call mwInit() as soon as you can, and mwTerm() at + the logical no-error ending of your program. Call mwAbort() + if the program is stopping due to an error; this will + terminate memwatch even if more than one call to mwTerm() is + outstanding. + + If you are using C++, remember that global and static C++ + objects constructors execute before main() when considering + where to put mwInit(). Also, their destructors execute after + main(). You may want to create a global object very early + with mwInit() in the constructor and mwTerm() in the + destructor. Too bad C++ does not guarantee initialization + order for global objects. + + If this didn't help, try adding a call to mwDoFlush(1) after + mwInit(). If THAT didn't help, then memwatch is unable to + create the log file. Check write permissions. + + If you can't use a log file, you can still use memwatch by + redirecting the output to a function of your choice. See the + next question. + +Q. I'd like memwatch's output to pipe to my fave debugger! How? + +A. Call mwSetOutFunc() with the address of a "void func(int c)" + function. You should also consider doing something about + the ARI handler, see memwatch.h for more details about that. + +Q. Why isn't there any C++ support? + +A. Because C++ is for sissies! =) Just kidding. + C++ comes with overridable allocation/deallocation + built-in. You can define your own new/delete operators + for any class, and thus circumvent memwatch, or confuse + it to no end. Also, the keywords "new" and "delete" may + appear in declarations in C++, making the preprocessor + replacement approach shaky. You can do it, but it's not + very stable. + + If someone were to write a rock solid new/delete checker + for C++, there is no conflict with memwatch; use them both. + +Q. I'm getting "WILD free" errors, but the code is bug-free! + +A. If memwatch's free() recieves a pointer that wasn't allocated + by memwatch, a "WILD free" message appears. If the source of + the memory buffer is outside of memwatch (a non-standard + library function, for instance), you can use mwFree_() to + release it. mwFree_() calls free() on the pointer given if + memwatch can't recognize it, instead of blocking it. + + Another source of "WILD free" messages is that if memwatch + is terminated before all memory allocated is freed, memwatch + will have forgotten about it, and thus generate the errors. + This is commonly caused by having memwatch auto-initialize, + and then using atexit() to clean up. When auto-initializing, + memwatch registers mwTerm() with atexit(), but if mwTerm() + runs before all memory is freed, then you will get "unfreed" + and "WILD free" messages when your own atexit()-registered + cleanup code runs, and frees the memory. + +Q. I'm getting "unfreed" errors, but the code is bug-free! + +A. You can get erroneous "unfreed" messages if memwatch + terminates before all memory has been freed. Try using + mwInit() and mwTerm() instead of auto-initialization. + + If you _are_ using mwInit() and mwTerm(), it may be that + some code in your program executes before mwInit() or + after mwTerm(). Make sure that mwInit() is the first thing + executed, and mwTerm() the last. + +Q. When compiling memwatch I get these 'might get clobbered' + errors, and something about a longjmp() inside memwatch. + +A. When using gcc or egcs with the optimization to inline + functions, this warning occurs. This is because gcc and + egcs inlines memwatch's functions with setjmp/longjmp, + causing the calling functions to become unstable. + + The gcc/egcs maintainers have been informed of this + problem, but until they modify the inline optimization + so that it leaves setjmp functions alone, make sure to + compile memwatch without inline function optimizations. + + gcc 2.95.2 can be patched for this, and I have been told + it will be fixed in an upcoming version. + +Q. My program crashes with SIGSEGV or alignment errors, but + only when I compile with memwatch enabled! + +A. You are using a 64-bit (or higher) platform, and memwatch + was unable to detect and adjust for this. You'll have to + either compile with a suitable define for mwROUNDALLOC, + I suggest (number of bits / 8), or define mwROUNDALLOC + directly in memwatch.c. + + Also, please check your limits.h file for the relevant + #defines, and tell me what they are. + +Q. When I include string.h after memwatch.h, I get errors + related to strdup(), what gives? + +A. Most, but probably not all, platforms are nice about + including files multiple times, so I could probably + avoid these errors by including string.h from memwatch.h. + But since I want to be on the safe side, I don't. + + To fix this, simply include string.h before memwatch.h, + or modify memwatch.h to include string.h. + Added: third-party/memwatch-2.71/Makefile =================================================================== --- third-party/memwatch-2.71/Makefile (rev 0) +++ third-party/memwatch-2.71/Makefile 2009-08-14 06:56:54 UTC (rev 214) @@ -0,0 +1,2 @@ +test: + $(CC) -DMEMWATCH -DMW_STDIO test.c memwatch.c Added: third-party/memwatch-2.71/README =================================================================== --- third-party/memwatch-2.71/README (rev 0) +++ third-party/memwatch-2.71/README 2009-08-14 06:56:54 UTC (rev 214) @@ -0,0 +1,99 @@ +README for MEMWATCH 2.69 + + This file should be enough to get you started, and should be + enough for small projects. For more info, see the files USING + and the FAQ. If this is not enough, see memwatch.h, which is + well documented. + + Memwatch is licensed under the GPL from version 2.69 + onwards. Please read the file gpl.txt for more details. + + If you choose to use memwatch to validate your projects, I + would like to hear about it. Please drop me a line at + jo...@li... about the project itself, the hardware, + operating system, compiler and any URL(s) you feel is + appropriate. + +***** To run the test program: + + Look at the source code for test.c first. It does some really + nasty things, and I want you to be aware of that. If memwatch + can't capture SIGSEGV (General Protection Fault for Windoze), + your program will dump core (crash for Windoze). + + Once you've done that, you can build the test program. + + Linux and other *nixes with gcc: + + gcc -o test -DMEMWATCH -DMEMWATCH_STDIO test.c memwatch.c + + Windows 95, Windows NT with MS Visual C++: + + cl -DMEMWATCH -DMEMWATCH_STDIO test.c memwatch.c + + Then simply run the test program. + + ./test + + +***** Quick-start instructions: + + 1. Make sure that memwatch.h is included in all of the + source code files. If you have an include file that + all of the source code uses, you might be able to include + memwatch.h from there. + + 2. Recompile the program with MEMWATCH defined. See your + compiler's documentation if you don't know how to do this. + The usual switch looks like "-DMEMWATCH". To have MEMWATCH + use stderr for some output (like, "Abort, Retry, Ignore?"), + please also define MW_STDIO (or MEMWATCH_STDIO, same thing). + + 3. Run the program and examine the output in the + log file "memwatch.log". If you didn't get a log file, + you probably didn't do step 1 and 2 correctly, or your + program crashed before memwatch flushed the file buffer. + To have memwatch _always_ flush the buffer, add a call + to "mwDoFlush(1)" at the top of your main function. + + 4. There is no fourth step... but remember that there + are limits to what memwatch can do, and that you need + to be aware of them: + +***** Limits to memwatch: + + Memwatch cannot catch all wild pointer writes. It can catch + those it could make itself due to your program trashing + memwatch's internal data structures. It can catch, sort of, + wild writes into No Mans Land buffers (see the header file for + more info). Anything else and you're going to get core dumped, + or data corruption if you're lucky. + + There are other limits of course, but that one is the most + serious one, and the one that you're likely to be suffering + from. + +***** Can use memwatch with XXXXX? + + Probably the answer is yes. It's been tested with several + different platforms and compilers. It may not work on yours + though... but there's only one way to find out. + +***** Need more assistance? + + I don't want e-mail on "how to program in C", or "I've got a + bug, help me". I _do_ want you to send email to me if you + find a bug in memwatch, or if it won't compile cleanly on your + system (assuming it's an ANSI-C compiler of course). + + If you need help with using memwatch, read the header file. + If, after reading the header file, you still can't resolve the + problem, please mail me with the details. + + I can be reached at "jo...@li...". + + The latest version of memwatch should be found at + "http://www.linkdata.se/". + + Johan Lindh + Added: third-party/memwatch-2.71/USING =================================================================== --- third-party/memwatch-2.71/USING (rev 0) +++ third-party/memwatch-2.71/USING 2009-08-14 06:56:54 UTC (rev 214) @@ -0,0 +1,213 @@ +Using memwatch +============== + +What is it? + + Memwatch is primarily a memory leak detector for C. Besides + detecting leaks, it can do a bunch of other stuff, but lets + stay to the basics. If you _really_ want to know all the + gory details, you should check out the header file, + memwatch.h, and the source code. It's actually got some + comments! (Whoa, what a concept!) + +How do I get the latest version? + + http://www.linkdata.se/sourcecode.html + ftp://ftp.linkdata.se/pub/memwatch/ + +How does it work? + + Using the C preprocessor, memwatch replaces all your + programs calls to ANSI C memory allocation functions with + calls to it's own functions, which keeps a record of all + allocations. + + Memwatch is very unobtrusive; unless the define MEMWATCH is + defined, memwatch removes all traces of itself from the + code (using the preprocessor). + + Memwatch normally writes it's data to the file + memwatch.log, but this can be overridden; see the section + on I/O, later. + +Can I use it for my C++ sources? + + You can, but it's not recommended. C++ allows individual + classes to have their own memory management, and the + preprocessor approach used by memwatch can cause havoc + with such class declarations if improperly used. + + If you have no such classes, or have them but still want + to test it, you can give it a try. + + First, re-enable the C++ support code in memwatch. + If you can't find it, you probably shouldn't be using + it. Then, in your source code, after including ALL + header files: + + #define new mwNew + #define delete mwDelete + + This will cause calls to new and delete in that source file + to be directed to memwatch. Also, be sure to read all the + text in memwatch.h regarding C++ support. + +Is this stuff thread-safe? + + I doubt it. As of version 2.66, there is rudimentary support + for threads, if you happen to be using Win32 or if you have + pthreads. Define WIN32 or MW_PTHREADS to signify this fact. + + This will cause a global mutex to be created, and memwatch + will lock it when accessing the global memory chain, but it's + still far from certified threadsafe. + +Initialization and cleanup + + In order to do it's work in a timely fashion, memwatch + needs to do some startup and cleanup work. mwInit() + initializes memwatch and mwTerm() terminates it. Memwatch + can auto-initialize, and will do so if you don't call + mwInit() yourself. If this is the case, memwatch will use + atexit() to register mwTerm() to the atexit-queue. + + The auto-init technique has a caveat; if you are using + atexit() yourself to do cleanup work, memwatch may + terminate before your program is done. To be on the safe + side, use mwInit() and mwTerm(). + + mwInit() and mwTerm() is nestable, so you can call mwInit() + several times, requiring mwTerm() to be called an equal + number of times to terminate memwatch. + + In case of the program aborting in a controlled way, you + may want to call mwAbort() instead of mwTerm(). mwAbort() + will terminate memwatch even if there are outstanding calls + to mwTerm(). + +I/O operations + + During normal operations, memwatch creates a file named + memwatch.log. Sometimes, memwatch.log can't be created; + then memwatch tries to create files name memwatNN.log, + where NN is between 01 and 99. If that fails, no log will + be produced. + + If you can't use a file log, or don't want to, no worry. + Just call mwSetOutFunc() with the address of a "void + func(int c)" function, and all output will be directed + there, character by character. + + Memwatch also has an Abort/Retry/Ignore handler that is + used when an ASSERT or VERIFY fails. The default handler + does no I/O, but automatically aborts the program. You can + use any handler you want; just send the address of a "int + func(const char*)" to mwSetAriFunc(). For more details on + that, see memwatch.h. + +TRACE/ASSERT/VERIFY macros + + Memwatch defines (if not already defined) the macros TRACE, + ASSERT and VERIFY. If you are already using macros with + these names, memwatch 2.61 and later will not override + them. Memwatch 2.61 and later will also always define the + macros mwTRACE, mwASSERT and mwVERIFY, so you can use these + to make sure you're talking to memwatch. Versions prior + to 2.61 will *OVERRIDE* existing TRACE, ASSERT and VERIFY. + + To make sure that existing TRACE, ASSERT and VERIFY macros + are preserved, you can define MW_NOTRACE, MW_NOASSERT and + MW_NOVERIFY. All versions of memwatch will abide by these. + +How slow can you go? + + Memwatch slows things down. Large allocations aren't + affected so that you can measure it, but small allocations + that would utilize a compilers small-allocator function + suddenly cannot, and so gets slowed down alot. As a worst + case, expect it to be 3-5 times slower. + + Free'ing gets hit worse, I'm afraid, as memwatch checks + a lot of stuff when freeing. Expect it to be 5-7 times + slower, no matter what the size of the allocation. + +Stress-testing the application + + You can simulate low-memory conditions using mwLimit(). + mwLimit() takes the maximum number of bytes to be + allocated; when the limit is hit, allocation requests will + fail, and a "limit" message will be logged. + + If you hit a real low-memory situation, memwatch logs that + too. Memwatch itself has some reserve memory tucked away so + it should continue running even in the worst conditions. + +Hunting down wild writes and other Nasty Things + + Wild writes are usually caused by using pointers that arent + initialized, or that were initialized, but then the memory + they points to is moved or freed. The best way to avoid + these kind of problems is to ALWAYS initialize pointers to + NULL, and after freeing a memory buffer, setting all + pointers that pointed to it to NULL. + + To aid in tracking down uninitialized pointers memwatch + zaps all memory with certain values. Recently allocated + memory (unless calloc'd, of course), contains 0xFE. + Recently freed memory contains 0xFD. So if your program + crashes when using memwatch and not without memwatch, it's + most likely because you are not initializing your allocated + buffers, or using the buffers after they've been freed. + + In the event that a wild pointer should damage memwatch's + internal data structures, memwatch employs checksums, + multiple copies of some values, and can also repair it's + own data structures. + + If you are a paranoid person, and as programmer you should + be, you can use memwatch's mwIsReadAddr() and + mwIsSafeAddr() functions to check the accessibility of + memory. These are implemented for both ANSI C systems and + Win32 systems. Just put an mwASSERT() around the check and + forget about it. + +Can I help? + + Well, sure. For instance, I like memwatch to compile + without any warnings or errors. If you are using an ANSI C + compliant compiler, and are getting warnings or errors, + please mail me the details and instructions on how to fix + them, if you can. + + Another thing you can do if you decide to use memwatch is + to mail me the name of the project(s) (and URL, if any), + hardware and operating system, compiler and what user + (organization). I will then post this info on the list of + memwatch users. + (http://www.linkdata.se/memwatchusers.html) + +Top five problems using memwatch + + 5. Passed a non-memwatch allocated pointer to memwatch's + free(). Symtom: Causes an erroneous "WILD free" log + entry to appear. Cure: Either include memwatch.h for + the file that allocates, or use mwFree_() to free it. + + 4. Relied on auto-initialization when using atexit(). + Symptom: Causes incorrect "unfreed" and "WILD free" + messages. Cure: Use mwInit() and mwTerm(). + + 3. Forgot to include memwatch.h in all files. Symptom: + Tends to generate "WILD free" and "unfreed" messages. + Cure: Make sure to include memwatch.h! + + 2. No write permissions in currect directory. Symptom: + Seems like memwatch 'just aint working'. Cure: Use + mwSetOutFunc() to redirect output. + + ...and the number one problem is... + + 1. Didn't define MEMWATCH when compiling. Symptom: + Memwatch dutifully disables itself. Cure: Try adding + -DMEMWATCH to the command line. + Added: third-party/memwatch-2.71/gpl.txt =================================================================== --- third-party/memwatch-2.71/gpl.txt (rev 0) +++ third-party/memwatch-2.71/gpl.txt 2009-08-14 06:56:54 UTC (rev 214) @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest va... [truncated message content] |
From: <Ste...@us...> - 2009-08-07 06:29:19
|
Revision: 213 http://pntool.svn.sourceforge.net/pntool/?rev=213&view=rev Author: StephenCamp Date: 2009-08-07 06:29:10 +0000 (Fri, 07 Aug 2009) Log Message: ----------- Dp has been partially debugged - still many known errors. Admcon, asiph, avpr, fvpr, and matrixmath have all had bugs found and fixed. Test routines for dp have been modified to make the logfiles generated during testing easier to deal with. Modified Paths: -------------- spnbox/admcon.c spnbox/asiph.c spnbox/avpr.c spnbox/dp.c spnbox/fvpr.c spnbox/matrixmath.c spnbox/tests/Makefile spnbox/tests/test-dp.c spnbox/tests/test-dp.txt Modified: spnbox/admcon.c =================================================================== --- spnbox/admcon.c 2009-08-04 20:31:44 UTC (rev 212) +++ spnbox/admcon.c 2009-08-07 06:29:10 UTC (rev 213) @@ -108,7 +108,7 @@ mem = CreateMemoryManager(3, 1, 0, 0); /*The constraint matrix is an identity followed below by those columns of DX which have indices present in p. We will do this by adding rows directly - to DX (it has been optimized for row ops). nulling out the columns we are not + to DX (it has been optimized for row ops), nulling out the columns we are not interested in, and putting in 1s for the identity where we are interested.*/ InsertNullRows(DX, 0, pCount, -1); ManageMatrix(&mem, DX); @@ -147,7 +147,7 @@ { int dm = GetMatrixEl(¶m->Dm, p[i], j); int dp = GetMatrixEl(¶m->Dp, p[i], j); - if (dm - dp < 0) F[p[i]] += (double) dm; + if (dp - dm < 0) F[p[i]] += (double) dm; } } @@ -466,7 +466,7 @@ { if (params->opl[i] > max) max = params->opl[i]; } - return max; + return max + 1; } /******************************************************************************* Modified: spnbox/asiph.c =================================================================== --- spnbox/asiph.c 2009-08-04 20:31:44 UTC (rev 212) +++ spnbox/asiph.c 2009-08-07 06:29:10 UTC (rev 213) @@ -272,7 +272,7 @@ for (place = 0; place < NumberOfRows(*Dm); place++) { /*Set newPlace to newRow && ! M(1, :)*/ - SetMatrixEl(&data->newPlace, 0, place, GetMatrixEl(&data->newRow, 0, place) && (! GetMatrixEl(&data->M, 0, place)) ? 1 : 0); + SetMatrixEl(&data->newPlace, 0, place, (GetMatrixEl(&data->newRow, 0, place) && ! GetMatrixEl(&data->M, 0, place)) ? 1 : 0); /*Set newRow to newRow | M(1, :)*/ if (GetMatrixEl(&data->M, 0, place)) { @@ -557,7 +557,7 @@ { /*We are going to add a row to NS consisting of the current column of sx.*/ /*Build a matrix (type-2 untransposed for optimization) and do an - insertion. This column insertion will be optimized)*/ + insertion. This row insertion will be optimized)*/ InsertRows(&data->NS, &rowSX, -1, -1); } /*If no siphons met the criteria, use ins to modify MNS and newIndex.*/ Modified: spnbox/avpr.c =================================================================== --- spnbox/avpr.c 2009-08-04 20:31:44 UTC (rev 212) +++ spnbox/avpr.c 2009-08-07 06:29:10 UTC (rev 213) @@ -180,4 +180,3 @@ } return 1; } - \ No newline at end of file Modified: spnbox/dp.c =================================================================== --- spnbox/dp.c 2009-08-04 20:31:44 UTC (rev 212) +++ spnbox/dp.c 2009-08-07 06:29:10 UTC (rev 213) @@ -33,8 +33,6 @@ matrix Dm, Dp, DI, Dcm, Dcp, L, L0, M; /*Constraint-related vectors*/ int *B, *B0, *G; - /*Maintain a count for G - it is not readily apparent what its count will be.*/ - int GCount; /*Place lists:*/ int *opl; /*Original places*/ int *ipl; /*Independent places*/ @@ -87,7 +85,6 @@ static int CheckParams(dp_p *p); static void Sort(int* array, int length); static void AddToArray(int** array, int length, int item); -static void AddToCountedArray(int **array, int* length, int item); static void AddToIndexArray(int** array, int* length, int item); static void UpdateDPData(dpData *data, char* description, void *newData); static MarkingConstraints UpdateMarkingConstraints(dpData *d); @@ -235,7 +232,7 @@ if (d.log) { if (d.firstpass) fprintf(d.dat, "\nIteration %d", d.iteration); - else fprintf(d.dat, "\nRun %d, iterariont %d", d.run, d.iteration); + else fprintf(d.dat, "\nRun %d, iteration %d", d.run, d.iteration); fflush(d.dat); } @@ -256,11 +253,11 @@ /*Bring the marking constraints down to target size.*/ if (NumberOfColumns(d.L) - d.targetRows > 0) { - RemoveColumns(&d.L, d.targetRows, NumberOfColumns(d.L) - d.targetRows, 2); + RemoveColumns(&d.L, d.targetRows, NumberOfColumns(d.L) - d.targetRows, -1); } if (NumberOfColumns(d.L0) - d.targetRows > 0) { - RemoveColumns(&d.L0, d.targetRows, NumberOfColumns(d.L0) - d.targetRows, 2); + RemoveColumns(&d.L0, d.targetRows, NumberOfColumns(d.L0) - d.targetRows, -1); } /*If there are any active transitions left, remove redundant constraints.*/ @@ -395,9 +392,9 @@ } else { - fprintf(d->log, "The supervisor may not enforce liveness.\n"); - fprintf(d->log, "The superviosr is guaranteed to be at least as permissive as the least\n"); - fprintf(d->log, "restrictive liveness enforcring supervisor"); + fprintf(d->log, ".\nThe supervisor may not enforce liveness.\n"); + fprintf(d->log, "The supervisor is guaranteed to be at least as permissive as the least\n"); + fprintf(d->log, "restrictive liveness enforcing supervisor"); } } else @@ -628,9 +625,9 @@ are present in the list of useful rows returned by reduce. Remove all other rows.*/ j = NumberOfRows(d->L) - 1; - for (i = count - 1; i >= 0; i--) + for (i = count - 1; i >= -1; i--) { - while(j > rcons.indf[i]) + while((i >= 0) ? j > rcons.indf[i] : j >= 0) { /*Remove the appropriate row from L.*/ RemoveRows(&d->L, j, 1, -1); @@ -647,9 +644,9 @@ are present in the list of useful rows returned by reduce. Remove all other rows.*/ j = NumberOfRows(d->L0) - 1; - for (i = NumberOfRows(rcons.Lf) - 1; i >= count; i--) + for (i = NumberOfRows(rcons.Lf) - 1; i >= count - 1; i--) { - while(j > rcons.indf[i] - NumberOfRows(d->L)) + while((i >= count) ? j > rcons.indf[i] - NumberOfRows(d->L) : j >= 0) { RemoveRows(&d->L0, j, 1, -1); for (k = j; k < NumberOfRows(d->L0); k++) @@ -700,7 +697,7 @@ /*Message printing.*/ if (is_verbose() >= VRB_DP) { - sprintf(message, "\nWorking on siphon %d of %d...", siphon + 1, NumberOfColumns(d->S)); + sprintf(message, "\nWorking on siphon %d of %d...", siphon + 1, siphons); PrintMessage(d, message); } @@ -713,11 +710,7 @@ if (cons.L.type) { - AddToArray(&cons.B, NumberOfRows(cons.L), b); - AllocateMatrixType(2, &l2, 1, NumberOfColumns(l)); - CopyMatrix(&l, &l2); - InsertRows(&cons.L, &l2, -1, -1); - chkconsRes = chkcons(&cons.L, cons.B, 0, 0); + chkconsRes = chkcons(&cons.L, cons.B, &l, b); } else { @@ -745,7 +738,7 @@ { SetMatrixEl(&a, 0, i, admconRes.l[i]); } - supervis_r supervisRes = supervis(&d->Dp, &d->Dm, &l); + supervis_r supervisRes = supervis(&d->Dp, &d->Dm, &a); /*Build l and b as before, but this time using a as the source.*/ BuildSiphonConstraint(d, &l, &b, &a, 0); @@ -768,7 +761,7 @@ if ((! GetMatrixEl(&d->S, i, siphon)) != (! GetMatrixEl(&a, i, 0))) { /*If such a place is encounted, set the generic variable x to 2 for - later use as a functon parameter.*/ + later use as a function parameter.*/ x = 2; break; } @@ -785,7 +778,7 @@ if (DoConstraintsApplyToAll(d, &supervisRes, &a, currentSiphon)) { /*Print constraint data.*/ - if (d->log) PrintConstraints(d, &l, b, currentSiphon, NumberOfRows(d->Dm) - 1, x); + if (d->log) PrintConstraints(d, &l, b, currentSiphon, NumberOfRows(d->Dm), x); /*Add the new place index to the dependent place list, the useful places list, and the new control places list.*/ AddToIndexArray(&d->dpl, &d->dpCount, NumberOfRows(supervisRes.Dfm) - 1); @@ -795,17 +788,20 @@ UpdateDPData(d, "Dm Dp", &supervisRes); memset(&supervisRes, 0, sizeof(supervis_r)); /*Add to the constraints. Make a copy of l first so that we can do - optimized row-adds and not do too many allocations.*/ - AddToArray(&d->B, NumberOfRows(d->L), NumberOfRows(d->L)); - AddToCountedArray(&d->G, &d->GCount, NumberOfRows(d->L)); + optimized row-adds and not do too many allocations.*/ AllocateMatrixType(2, &l2, 1, NumberOfColumns(l)); CopyMatrix(&l, &l2); AddToArray(&d->B, NumberOfRows(d->L), b); - AddToCountedArray(&d->G, &d->GCount, b); + AddToArray(&d->G, NumberOfRows(d->L), b); InsertRows(&d->L, &l, -1, -1); InsertRows(&d->M, &l2, -1, -1); - /*Add a null column to the end of S. */ - InsertNullColumns(&d->S, -1, 1, -1); + /*Add a null row to the end of S and allocate enough space for the + new siphon array.*/ + InsertNullRows(&d->S, -1, 1, -1); + int *newCSiphon = tcalloc(NumberOfRows(d->S), sizeof(int)); + memcpy(newCSiphon, currentSiphon, sizeof(int) * (NumberOfRows(d->S) - 1)); + free(currentSiphon); + currentSiphon = newCSiphon; } else { @@ -859,7 +855,6 @@ { int i, j, k; - /*Transition split.*/ msplit_r msplitRes = msplit(&d->Dm, &d->Dp, 0, &d->M, &d->L0, &d->L, d->ipl, d->ipCount, d->dpl, d->dpCount, d->TD, d->TDCount); UpdateDPData(d, "free matrix Dm Dp M L0 L ipl ipCount TD TDCount", &msplitRes); @@ -874,9 +869,12 @@ { ncp[d->cpl[i]] = 1; } - + /* For debugging purposes, we replace the pn2eacpn call with a pn2acpn call. pn2eacpn_r pn2eacpnRes = pn2eacpn(&d->Dm, &d->Dp, ncp, &d->M, &d->L0, &d->L, d->ipl, d->ipCount, d->dpl, d->dpCount, d->TD, d->TDCount); UpdateDPData(d, "free matrix Dm Dp M L0 L ipl ipCount TD TDCount", &pn2eacpnRes); + */ + pn2acpn_r pn2acpnRes = pn2acpn(&d->Dm, &d->Dp, ncp, &d->M, &d->L0, &d->L, d->ipl, d->ipCount, d->dpl, d->dpCount); + UpdateDPData(d, "free matrix Dm Dp M L0 L ipl ipCount", &pn2acpnRes); free(ncp); } @@ -934,6 +932,10 @@ } j++; } + while (k < d->ExcludeCount) + { + d->ExcludeT[k++] = j++; + } } else { @@ -998,7 +1000,7 @@ the siphon.*/ for (j = 0; j < NumberOfRows(d->S); j++) { - if (GetMatrixEl(&supervisRes->Dfp, j, i)) break; + if (GetMatrixEl(&supervisRes->Dfp, j, i) && siphon[j]) break; } /*If there were none, set the flag and break out of the loop.*/ if (j == NumberOfRows(d->S)) @@ -1042,7 +1044,7 @@ break; } } - if (j == NumberOfColumns(d->Dcm)) newApl[newApCount++] = i; + if (j != NumberOfColumns(d->Dcm)) newApl[newApCount++] = i; } free(d->apl); d->apl = newApl; @@ -1112,9 +1114,9 @@ { for (i = 0; i < NumberOfRows(d->S); i++) { - if (GetMatrixEl(&d->Dm, i, j) && ! (siphon[i] || ExcludeFlag[i])) + if (GetMatrixEl(&d->Dm, i, j) && siphon[i] && ! ExcludeFlag[j]) { - ExcludeFlag[i] = 1; + ExcludeFlag[j] = 1; k++; } } @@ -1219,7 +1221,8 @@ through the whole matrix twice, preallocate newApl to its maximum possible size.*/ int *newApl = tcalloc(NumberOfRows(d->Dcm), sizeof(int)); - int newApCount = 0, i, j; + int i, j; + d->apCount = 0; for (i = 0; i < NumberOfRows(d->Dcm); i++) { for (j = 0; j < NumberOfColumns(d->Dcm); j++) @@ -1229,11 +1232,10 @@ break; } } - if (j != NumberOfColumns(d->Dcm)) newApl[newApCount++] = i; + if (j != NumberOfColumns(d->Dcm)) newApl[d->apCount++] = i; } free(d->apl); - d->apl = newApl; - d->apCount = newApCount; + d->apl = newApl; /*Build a list of places that will be considered for siphon computation. This is any place such that it is present in both the useful and the active place @@ -1253,7 +1255,7 @@ /*Make sure TSIPH is the right size.*/ if (NumberOfRows(d->TSIPH) < NumberOfRows(d->Dm)) { - InsertNullRows(&d->TSIPH, NumberOfRows(d->Dm) - NumberOfRows(d->TSIPH), -1, -1); + InsertNullRows(&d->TSIPH, -1, NumberOfRows(d->Dm) - NumberOfRows(d->TSIPH), -1); } /*Remove any columns from TSIPH such that they have no nonzero entries in rows corresponding to active places.*/ @@ -1338,8 +1340,10 @@ { /*If we get here we are doing (T-)liveness enforcement. Transform the net to an EAC net.*/ - pn2eacpn_r pn2eacpnRes = pn2eacpn(&d->Dm, &d->Dp, 0, &d->M, &d->L0, &d->L, d->ipl, d->ipCount, d->dpl, d->dpCount, d->TD, d->TDCount); - UpdateDPData(d, "free matrix Dm Dp M L0 L ipl ipCount TD TDCount", &pn2eacpnRes); + /*pn2eacpn_r pn2eacpnRes = pn2eacpn(&d->Dm, &d->Dp, 0, &d->M, &d->L0, &d->L, d->ipl, d->ipCount, d->dpl, d->dpCount, d->TD, d->TDCount); + UpdateDPData(d, "free matrix Dm Dp M L0 L ipl ipCount TD TDCount", &pn2eacpnRes);*/ + pn2acpn_r pn2acpnRes = pn2acpn(&d->Dm, &d->Dp, 0, &d->M, &d->L0, &d->L, d->ipl, d->ipCount, d->dpl, d->dpCount); + UpdateDPData(d, "free matrix Dm Dp M L0 L ipl ipCount", &pn2acpnRes); /*Find the t-minimal active subnet.*/ tactn_r tactnRes = tactn(&d->Dm, &d->Dp, d->IncludeT, d->IncludeCount, d->ExcludeT, d->ExcludeCount, 0, 0, 1); @@ -1433,7 +1437,6 @@ CopyMatrix(&d->L, &d->M); d->G = tcalloc(NumberOfRows(d->L), sizeof(int)); memcpy(d->G, d->B, NumberOfRows(d->L) * sizeof(int)); - d->GCount = NumberOfRows(d->L); } } @@ -1536,7 +1539,7 @@ MRow[d->ipl[j]] = GetMatrixEl(&d->M, i, j); } /*Display the row.*/ - fprintf(d->log, "\n %d --> %s >= %d", d->dpl[i], avpr(MRow, NumberOfRows(d->Dm), DISPLAY_INTS, 0, 0)); + fprintf(d->log, "\n %d --> %s >= %d", d->dpl[i], avpr(MRow, NumberOfRows(d->Dm), DISPLAY_INTS, 0, 0), d->G[i]); } free(MRow); @@ -1590,6 +1593,8 @@ DeallocateMatrix(&d->Dp); AllocateMatrixType(2, &d->Dp, NumberOfRows(p->Dp), NumberOfColumns(p->Dp)); CopyMatrix(&p->Dp, &d->Dp); + DeallocateMatrix(&d->DI); + d->DI = SubtractMatrix(&d->Dp, &d->Dm, (matrix*) 2); /*If either of the constraint matrices is not present, initialize it to have the right number of columns and zero rows so that it can be concatenated with the other to form the total constraint matrix.*/ @@ -2018,19 +2023,12 @@ through an array that is already properly sorted, so this is low-cost.*/ void AddToIndexArray(int** array, int* length, int item) { - AddToCountedArray(array, length, item); - Sort(*array, *length); -} - -/******************************************************************************* -This function adds an item to an array and increments its count.*/ -void AddToCountedArray(int **array, int* length, int item) -{ int *newArray = tcalloc(*length + 1, sizeof(int)); memcpy(newArray, *array, sizeof(int) * (*length)); newArray[(*length)++] = item; free(*array); *array = newArray; + Sort(*array, *length); } /******************************************************************************* Modified: spnbox/fvpr.c =================================================================== --- spnbox/fvpr.c 2009-08-04 20:31:44 UTC (rev 212) +++ spnbox/fvpr.c 2009-08-07 06:29:10 UTC (rev 213) @@ -144,5 +144,3 @@ } return 1; } - - \ No newline at end of file Modified: spnbox/matrixmath.c =================================================================== --- spnbox/matrixmath.c 2009-08-04 20:31:44 UTC (rev 212) +++ spnbox/matrixmath.c 2009-08-07 06:29:10 UTC (rev 213) @@ -206,7 +206,7 @@ int i, j; if (! m) { - printf ("Matrix $s (null pointer).\n", title); + printf ("Matrix %s (null pointer).\n", title); return; } printf("Matrix %s (%d x %d of type %d):\n", title, NumberOfRows(*m), NumberOfColumns(*m), m->type); Modified: spnbox/tests/Makefile =================================================================== --- spnbox/tests/Makefile 2009-08-04 20:31:44 UTC (rev 212) +++ spnbox/tests/Makefile 2009-08-07 06:29:10 UTC (rev 213) @@ -29,7 +29,7 @@ PN2EACPN=pn2eacpn.o $(NLTRANS) REDUCE=reduce.o chkcons.o $(IPSOLVE) TACTN=tactn.o $(IPSOLVE) -DP=dp.o tactn.o reduce.o chkcons.o pn2eacpn.o nltrans.o asiph.o actn.o admcon.o supervis.o msplit.o issiph.o fvpr.o avpr.o $(EXTENDEDMATRIX) $(IPSOLVE) +DP=dp.o tactn.o reduce.o chkcons.o pn2acpn.o nltrans.o asiph.o actn.o admcon.o supervis.o msplit.o issiph.o fvpr.o avpr.o $(EXTENDEDMATRIX) $(IPSOLVE) #Common test header dependencies. COMMONHEADER=../spnbox.h test.h ../../pnheaders/pns.h ../../pnheaders/matrix.h ../matrixmath.h ../MemoryManager.h StructuredIO.h Modified: spnbox/tests/test-dp.c =================================================================== --- spnbox/tests/test-dp.c 2009-08-04 20:31:44 UTC (rev 212) +++ spnbox/tests/test-dp.c 2009-08-07 06:29:10 UTC (rev 213) @@ -29,9 +29,10 @@ //Before we begin, delete any old log files. remove("dp.log"); remove("dp.dat"); - + int transitions; while (ParseStructure(input, iDesc, &iFill, &mem, &D, &p.Dm, &p.Dp, &p.Tuc, &p.TucCount, &p.Tuo, &p.TuoCount, &p.IncludeT, &p.IncludeCount, &p.ExcludeT, &p.ExcludeCount, &p.B, &BCount, &p.B0, &B0Count, &p.L, &p.L0, WriteLog, EnforceLive)) { + transitions = (iFill[0] ? NumberOfColumns(D) : (iFill[1] ? NumberOfColumns(p.Dm) : (iFill[2] ? NumberOfColumns(p.Dp) : 0))); DisplayStructure(iDesc, iFill, &D, &p.Dm, &p.Dp, p.Tuc, p.TucCount, NumberOfColumns(p.Dm), p.Tuo, p.TuoCount, NumberOfColumns(p.Dm), p.IncludeT, p.IncludeCount, p.ExcludeT, p.ExcludeCount, p.B, BCount, p.B0, B0Count, &p.L, &p.L0, WriteLog, EnforceLive); FillDmDp(iFill, &D, &p.Dm, &p.Dp, &mem); /*Log writing defaults to on.*/ Modified: spnbox/tests/test-dp.txt =================================================================== --- spnbox/tests/test-dp.txt 2009-08-04 20:31:44 UTC (rev 212) +++ spnbox/tests/test-dp.txt 2009-08-07 06:29:10 UTC (rev 213) @@ -2,8 +2,12 @@ rem arrayi IncludeT, arrayi ExcludeT, arrayi B, arrayi B0, matrix L, matrix L0, rem string WriteLog = on/off, string EnforceLive = on/off +echo Deadlock prevention tests. echo Problem 1. echo Example 5.2 from [Iordache, 2000] +echo Answer should be: +echo L = [ 2 2 1 ] +echo b = [ 2 ] Dp 3 5 0 1 0 1 0 0 0 1 0 1 @@ -63,6 +67,14 @@ echo Problem 5. echo Example 5.1 from [Iordache, 2000]. +echo Answer should be: +echo L = [ 1 1 0 0 ] +echo ....[ 0 0 1 1 ] +echo ....[ 1 1 1 1 ] +echo B = [ 1 ] +echo ....[ 1 ] +echo ....[ 3 ] + Dm 4 5 1 0 1 0 1 0 0 0 1 0 @@ -78,6 +90,11 @@ echo Problem 6. echo The same data from problem 5 but with nonzero initial constraints. +echo Answer should have rows: +echo L = [ 1 1 0 0 ] B = [ 1 ] +echo ....[ 0 0 1 1 ] [ 1 ] +echo ....[ 1 1 1 1 ] [ 3 ] + Dm 4 5 1 0 1 0 1 0 0 0 1 0 @@ -114,10 +131,14 @@ echo Problem 8. echo Example 5.3 in [Iordache, 2000]. Transition t1 is unobservable. +echo Answer should be: +echo L = [ 2 0 1 ] B = [ 1 ] +echo .....[ 0 2 1 ] [ 1 ] +echo L0 = [ 2 2 2 ] B0 = [ 3 ] D 3 3 --1 -1 2 - 1 0 -1 - 0 1 -1 +-1 1 0 +-1 0 1 + 2 -1 -1 Tuo 1 0 done This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ee...@us...> - 2009-08-04 20:31:54
|
Revision: 212 http://pntool.svn.sourceforge.net/pntool/?rev=212&view=rev Author: eegs002 Date: 2009-08-04 20:31:44 +0000 (Tue, 04 Aug 2009) Log Message: ----------- Fixed includes in process array to be of type char* instead of text Modified Paths: -------------- codegen/src/main.c codegen/src/plantCompiler.c codegen/src/plantCompiler.h codegen/src/text.c codegen/src/text.h Modified: codegen/src/main.c =================================================================== --- codegen/src/main.c 2009-08-03 20:00:13 UTC (rev 211) +++ codegen/src/main.c 2009-08-04 20:31:44 UTC (rev 212) @@ -19,13 +19,15 @@ int labelsp1[] = {0,1,2}; pns plant1 = createpn("pnum tnum D m0 label",3,3,Dp1,mp1,labelsp1); - text includesP1 = createText("includes.txt",11,28); + //text includesP1 = createText("includes.txt",11,28); + char includesP1[50]; + sprintf(includesP1,"//Plant 1 includes\n"); updatepn(&plant1, "segment", 0 ,"printf(\"This is PLACE 1!\");"); updatepn(&plant1, "segment", 1 ,"printf(\"This is PLACE 2!\");"); updatepn(&plant1, "segment", 2 ,"printf(\"This is PLACE 3!\");"); - process proc1 = createProc("plant-1.c",&plant1,0,1, "BUILD COMMAND", &includesP1); + process proc1 = createProc("plant-1.c",&plant1,0,1, "BUILD COMMAND", includesP1); //PLANT 2 int Dp2[] = {-1,1, @@ -34,12 +36,15 @@ int labelsp2[] = {0,1}; pns plant2 = createpn("pnum tnum D m0 label",2,2,Dp2,mp2,labelsp2); - text includesP2 = createText("includes.txt",46,63); + //text includesP2 = createText("includes.txt",46,63); + char includesP2[50]; + sprintf(includesP2,"//Plant 2 includes\n"); + updatepn(&plant2, "segment", 0 ,"printf(\"PLANT 2: This is PLACE 1!\");"); updatepn(&plant2, "segment", 1 ,"printf(\"PLANT 2: This is PLACE 2!\");"); - process proc2 = createProc("plant-2.c",&plant2,0,1, "BUILD COMMAND", &includesP2); + process proc2 = createProc("plant-2.c",&plant2,0,1, "BUILD COMMAND", includesP2); //SUPERVISOR int Ds[] = {-1,1}; @@ -61,8 +66,8 @@ printf("\nCode generation complete\n"); - fclose(includesP1.input); - fclose(includesP2.input); + //fclose(includesP1.input); + //fclose(includesP2.input); return 0; Modified: codegen/src/plantCompiler.c =================================================================== --- codegen/src/plantCompiler.c 2009-08-03 20:00:13 UTC (rev 211) +++ codegen/src/plantCompiler.c 2009-08-04 20:31:44 UTC (rev 212) @@ -60,7 +60,7 @@ // //////////////////////////////////////////////////////////////////////// -void compileSinglePlant(pns *pnsPlant, FILE* plantFile, text *includes) +void compileSinglePlant(pns *pnsPlant, FILE* plantFile, char *includes) { createIncludes(plantFile, includes); @@ -140,9 +140,11 @@ -void createIncludes(FILE* plantFile, text *includes) +void createIncludes(FILE* plantFile, char *includes) { - retrieveIncludes(plantFile, includes); + //retrieveIncludes(plantFile, includes); + fprintf(plantFile,"\n//Includes from specs\n"); + fprintf(plantFile,includes); fprintf(plantFile,"#include \"pns.h\"\n"); fprintf(plantFile,"#include \"matrix.h\"\n"); fprintf(plantFile,"#include <signal.h>\n"); Modified: codegen/src/plantCompiler.h =================================================================== --- codegen/src/plantCompiler.h 2009-08-03 20:00:13 UTC (rev 211) +++ codegen/src/plantCompiler.h 2009-08-04 20:31:44 UTC (rev 212) @@ -34,7 +34,7 @@ // //////////////////////////////////////////////////////////////////////// -void compileSinglePlant(pns *pnsPlant, FILE* plantFile, text *includes); +void compileSinglePlant(pns *pnsPlant, FILE* plantFile, char *includes); @@ -72,7 +72,7 @@ //Generate the include statements -void createIncludes(FILE* plantFile, text *includes); +void createIncludes(FILE* plantFile, char *includes); //Retrieve the includes statements from the file void retrieveIncludes(FILE* plantFile, text *includes); Modified: codegen/src/text.c =================================================================== --- codegen/src/text.c 2009-08-03 20:00:13 UTC (rev 211) +++ codegen/src/text.c 2009-08-04 20:31:44 UTC (rev 212) @@ -33,7 +33,7 @@ process createProc(char *pName, pns *pnPtr,int pType,\ - int pStart, char *pBuild, text *pInclude) + int pStart, char *pBuild, char *pInclude) { process proc; Modified: codegen/src/text.h =================================================================== --- codegen/src/text.h 2009-08-03 20:00:13 UTC (rev 211) +++ codegen/src/text.h 2009-08-04 20:31:44 UTC (rev 212) @@ -20,4 +20,4 @@ //This can be used to create process structure defined in pns.h process createProc(char *pName, pns *pnPtr,int pType,\ - int pStart, char *pBuild, text *pInclude); + int pStart, char *pBuild, char *pInclude); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-08-03 20:00:29
|
Revision: 211 http://pntool.svn.sourceforge.net/pntool/?rev=211&view=rev Author: StephenCamp Date: 2009-08-03 20:00:13 +0000 (Mon, 03 Aug 2009) Log Message: ----------- The dp tests now complete without any runtime errors. There are still logic errors to be debugged, but this seems like a good time to back up my source. While debugging dp.c, found and corrected bugs in admcon, fvpr, and the dp test routines. Modified Paths: -------------- spnbox/admcon.c spnbox/dp.c spnbox/fvpr.c spnbox/tests/test-dp.c spnbox/tests/test-dp.txt Modified: spnbox/admcon.c =================================================================== --- spnbox/admcon.c 2009-07-31 22:09:33 UTC (rev 210) +++ spnbox/admcon.c 2009-08-03 20:00:13 UTC (rev 211) @@ -9,7 +9,7 @@ static int CheckParams(admcon_p *params); static int GetRowCount(admcon_p *params); static matrix BuildZ(admcon_p *params); -static matrix BuildDX(admcon_p *p, admcon_r *result, matrix *Z); +static matrix BuildDX(admcon_p *p, matrix *Z); static int *nlplace(admcon_p *p, matrix *DX, int *pCount); static ipsolve_r RawSolution(admcon_p *param, matrix *DX, int* p, int pCount); static admcon_r BuildResult(ipsolve_r *lpresult, int *p, int pCount, int rowCount); @@ -27,22 +27,23 @@ } /*Initialize the result to a default value.*/ - if (params->siphon) - { - result.l = tcalloc(NumberOfRows(params->Dm), sizeof(int)); - memcpy(result.l, params->siphon, sizeof(int) * NumberOfRows(params->Dm)); - } result.how = 1; /*Get the row count and the intermediate matrix Z.*/ int rowCount = GetRowCount(params); matrix Z = BuildZ(params); /*Get the intermediate linear programming matrix DX. Z will be deallocated - by the function call. - If DX returns an empty matrix, it means that the current solution is - feasible. Return immediately.*/ - matrix DX = BuildDX(params, &result, &Z); - if (! DX.type) return result; + by the function call. If DX returns an empty matrix, it means that the + default solution, a copy of the siphon, is feasible. Return immediately.*/ + matrix DX = BuildDX(params, &Z); + if (! DX.type) + { + /*Build the result and return. l should be a copy of the siphon vector.*/ + result.l = tcalloc(NumberOfRows(params->Dm), sizeof(int)); + result.lCount = NumberOfRows(params->Dm); + memcpy(result.l, params->siphon, sizeof(int) * NumberOfRows(params->Dm)); + return result; + } /*Get p, a list of places. This function is an aggregate of the nlplace function present in the Matlab version of this function, and several lines of code @@ -51,8 +52,8 @@ int pCount; int *p; if (! (p = nlplace(params, &DX, &pCount))) - { - memset(&result, 0, sizeof(admcon_r)); + { + result.how = 0; DeallocateMatrix(&DX); return result; } @@ -61,8 +62,7 @@ using p. This problem deallocates DX.*/ ipsolve_r lpresult = RawSolution(params, &DX, p, pCount); - /*Get the new solution (Deallocate the space used by the old first)*/ - free(result.l); + /*Get the new solution.*/ return BuildResult(&lpresult, p, pCount, rowCount); } @@ -309,7 +309,7 @@ correct it returns an empty matrix to signify that admcon should return immediately. This function also deallocates the Z matrix, which, is not used again.*/ -matrix BuildDX(admcon_p *p, admcon_r *result, matrix *Z) +matrix BuildDX(admcon_p *p, matrix *Z) { /*DX is a matrix composed of a right-to-left concatentation of submatrices, all transposed: DX = [Auc, Auo, -Auo, -Ds, d]' @@ -354,26 +354,29 @@ /*Deallocate Z. It will not be needed anymore.*/ DeallocateMatrix(Z); - /*Run a test. If DX * l (the current solution vector) >= b, the current - solution vector is good. b should be a vector of all zeros except for the last - element, which should be 1. We can skip the building of b and simply put the - test in a loop.*/ - for (i = 0; i < NumberOfRows(DX); i++) + /*Run a test. If DX * siphon (the default solution vector is simply the siphon) + >= b, the default solution vector is good. b should be a vector of all zeros + except for the last element, which should be 1. We can skip the building of b + and simply put the test in a loop.*/ + if (p->siphon) { - k = MultiplyVector(&DX, (matrix*) result->l, i, MULTIPLYVECTOR_ARRAY, 0); - if (k < (i < NumberOfRows(DX) - 1 ? 0 : 1)) + for (i = 0; i < NumberOfRows(DX); i++) { - break; + k = MultiplyVector(&DX, (matrix*) p->siphon, i, MULTIPLYVECTOR_ARRAY, 0); + if (k < (i < NumberOfRows(DX) - 1 ? 0 : 1)) + { + break; + } } + /*If we made it through the loop without breaking out early, it means that the + default solution vector is valid. Deallocate and zero DX and return to + indicate this. Otherwise just return DX as-is for the next stage in + processing.*/ + if (i == NumberOfRows(DX)) + { + DeallocateMatrix(&DX); + } } - /*If we made it through the loop without breaking out early, it means that the - current solution vector is valid. Deallocate and zero DX and return to - indicate this. Otherwise just return DX as-is for the next stage in - processing.*/ - if (i == NumberOfRows(DX)) - { - DeallocateMatrix(&DX); - } return DX; } @@ -433,7 +436,7 @@ { for (k = 0; k < p->dpCount; k++) { - SetMatrixEl(&result, p->dpl[k], j, GetMatrixEl(&p->M, i, k)); + SetMatrixEl(&result, p->dpl[k], j, GetMatrixEl(&p->M, k, i)); } } Modified: spnbox/dp.c =================================================================== --- spnbox/dp.c 2009-07-31 22:09:33 UTC (rev 210) +++ spnbox/dp.c 2009-08-03 20:00:13 UTC (rev 211) @@ -328,7 +328,8 @@ free(d->Tuo); free(d->TDCount); DeallocateMatrix(&d->TSIPH); - DeallocateMatrix(&d->S); + /*S may not ever have been allocated if no new siphons were found.*/ + if (d->S.type) DeallocateMatrix(&d->S); memset(d, 0, sizeof(dpData)); } @@ -612,6 +613,9 @@ void ReduceLB(dpData *d) { MarkingConstraints cons = UpdateMarkingConstraints(d); + //If there are no constraints, return immediately. + if (! cons.L.type) return; + reduce_r rcons = reduce(&cons.L, cons.B); free(cons.B); DeallocateMatrix(&cons.L); @@ -798,8 +802,8 @@ CopyMatrix(&l, &l2); AddToArray(&d->B, NumberOfRows(d->L), b); AddToCountedArray(&d->G, &d->GCount, b); - InsertRows(&d->L, &l, -1, 1); - InsertRows(&d->M, &l2, -1, 1); + InsertRows(&d->L, &l, -1, -1); + InsertRows(&d->M, &l2, -1, -1); /*Add a null column to the end of S. */ InsertNullColumns(&d->S, -1, 1, -1); } @@ -808,7 +812,7 @@ /*Add the built constraint to the initial marking constraints.*/ if (d->log) PrintConstraints(d, &l, b, currentSiphon, 0, x); AddToArray(&d->B0, NumberOfRows(d->L0), NumberOfRows(d->L0)); - InsertRows(&d->L0, &l, -1, 1); + InsertRows(&d->L0, &l, -1, -1); } } else @@ -836,13 +840,13 @@ d->uci = 1; d->state.perm = 0; d->upd = 0; - if (d->log) PrintConstraints(d, 0, 0, 0, -2, 1); + if (d->log) PrintConstraints(d, 0, 0, currentSiphon, -2, 1); } DeallocateAdmcon(&admconRes); } else { - if (d->log) PrintConstraints(d, 0, 0, 0, -1, 0); + if (d->log) PrintConstraints(d, 0, 0, currentSiphon, -1, 0); } } } @@ -1052,6 +1056,7 @@ admconP.Dm = d->Dm; admconP.Dp = d->Dp; admconP.DI = d->DI; + admconP.M = d->M; admconP.ipl = d->ipl; admconP.dpl = d->dpl; admconP.opl = d->opl; @@ -1224,7 +1229,7 @@ break; } } - if (j == NumberOfColumns(d->Dcm)) newApl[newApCount++] = i; + if (j != NumberOfColumns(d->Dcm)) newApl[newApCount++] = i; } free(d->apl); d->apl = newApl; @@ -1778,8 +1783,9 @@ { d.state.uncontro = 1; } - /*If L or L0 are present, set the initial conditions (incon) state bit.*/ - if (d.L.type || d.L0.type) + /*If L or L0 are present (have at least one row), set the initial conditions + (incon) state bit.*/ + if (d.L.nr || d.L0.nr) { d.state.incon = 1; d.consis = 1; @@ -1824,15 +1830,16 @@ it in the MarkingConstraints structure.*/ MarkingConstraints UpdateMarkingConstraints(dpData *d) { - int count; + int count, cols; MarkingConstraints result; memset(&result, 0, sizeof(MarkingConstraints)); if (NumberOfRows(d->L) || NumberOfRows(d->L0)) { count = NumberOfRows(d->L) + NumberOfRows(d->L0); - AllocateMatrixType(2, &result.L, count, NumberOfRows(d->Dm)); - CopyBlock(NumberOfRows(d->L), NumberOfRows(d->Dm), &d->L, 0, 0, &result.L, 0, 0); - CopyBlock(NumberOfRows(d->L0), NumberOfRows(d->Dm), &d->L0, 0, 0, &result.L, NumberOfRows(d->L), 0); + cols = NumberOfColumns(d->L) ? NumberOfColumns(d->L) : NumberOfColumns(d->L0); + AllocateMatrixType(2, &result.L, count, cols); + CopyBlock(NumberOfRows(d->L), cols, &d->L, 0, 0, &result.L, 0, 0); + CopyBlock(NumberOfRows(d->L0), cols, &d->L0, 0, 0, &result.L, NumberOfRows(d->L), 0); } if (count && (d->B || d->B0)) { Modified: spnbox/fvpr.c =================================================================== --- spnbox/fvpr.c 2009-07-31 22:09:33 UTC (rev 210) +++ spnbox/fvpr.c 2009-08-03 20:00:13 UTC (rev 211) @@ -79,7 +79,7 @@ int GetBufferLength(void* vector, int length, int mode, char* op, char* cl) { - if (length == 0) return 1; + if (length == 0) return 3; /*The buffer length will be, at most, the vector length times the length of the element separator plus the number of digits required to display the largest number in the vector, all plus the lengths of the beginning and ending @@ -101,7 +101,7 @@ digits++; } - return strlen(op) + strlen(cl) + ((strlen(", ") + digits) * length) + 1 + (mode == DISPLAY_MATRIX) ? 1 : 0; + return strlen(op) + strlen(cl) + ((strlen(", ") + digits) * length) + 1 + ((mode == DISPLAY_MATRIX) ? 1 : 0); } int GetVectorEl(void* vector, int i, int mode) Modified: spnbox/tests/test-dp.c =================================================================== --- spnbox/tests/test-dp.c 2009-07-31 22:09:33 UTC (rev 210) +++ spnbox/tests/test-dp.c 2009-08-03 20:00:13 UTC (rev 211) @@ -26,9 +26,13 @@ setverbose(VRB_MAX); + //Before we begin, delete any old log files. + remove("dp.log"); + remove("dp.dat"); + while (ParseStructure(input, iDesc, &iFill, &mem, &D, &p.Dm, &p.Dp, &p.Tuc, &p.TucCount, &p.Tuo, &p.TuoCount, &p.IncludeT, &p.IncludeCount, &p.ExcludeT, &p.ExcludeCount, &p.B, &BCount, &p.B0, &B0Count, &p.L, &p.L0, WriteLog, EnforceLive)) { - DisplayStructure(iDesc, iFill, &D, &p.Dm, &p.Dp, p.Tuc, p.TucCount, p.Tuo, p.TuoCount, p.IncludeT, p.IncludeCount, p.ExcludeT, p.ExcludeCount, p.B, BCount, p.B0, B0Count, &p.L, &p.L0, WriteLog, EnforceLive); + DisplayStructure(iDesc, iFill, &D, &p.Dm, &p.Dp, p.Tuc, p.TucCount, NumberOfColumns(p.Dm), p.Tuo, p.TuoCount, NumberOfColumns(p.Dm), p.IncludeT, p.IncludeCount, p.ExcludeT, p.ExcludeCount, p.B, BCount, p.B0, B0Count, &p.L, &p.L0, WriteLog, EnforceLive); FillDmDp(iFill, &D, &p.Dm, &p.Dp, &mem); /*Log writing defaults to on.*/ if (strcmp(WriteLog, "off")) p.option |= DP_OPT_WRITELOG; @@ -45,6 +49,7 @@ printf("Should be 'off' or 'on'. Defaulting to 'off'.\n"); } + //For the duration of a test, append to the log files. p.option |= DP_OPT_APPENDLOGS; dp_r res = dp(&p); Modified: spnbox/tests/test-dp.txt =================================================================== --- spnbox/tests/test-dp.txt 2009-07-31 22:09:33 UTC (rev 210) +++ spnbox/tests/test-dp.txt 2009-08-03 20:00:13 UTC (rev 211) @@ -90,7 +90,7 @@ 3 0 0 0 0 0 1 0 0 0 -L 4 4 +L 1 4 1 1 1 1 B 1 3 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-31 22:09:44
|
Revision: 210 http://pntool.svn.sourceforge.net/pntool/?rev=210&view=rev Author: StephenCamp Date: 2009-07-31 22:09:33 +0000 (Fri, 31 Jul 2009) Log Message: ----------- dp.c has been added but NOT DEBUGGED (I am adding it for backup purposes - there are still many errors) Added test routines and scripts for dp. Modified spnbox.h and the makefiles to include dp.c. Fixed bugs in admcon.c and asiph.c. Modified Paths: -------------- spnbox/Makefile spnbox/admcon.c spnbox/asiph.c spnbox/deallocation.c spnbox/spnbox.h spnbox/tests/Makefile Added Paths: ----------- spnbox/dp.c spnbox/tests/test-dp.c spnbox/tests/test-dp.txt Property Changed: ---------------- spnbox/tests/ Modified: spnbox/Makefile =================================================================== --- spnbox/Makefile 2009-07-28 16:49:11 UTC (rev 209) +++ spnbox/Makefile 2009-07-31 22:09:33 UTC (rev 210) @@ -14,7 +14,7 @@ asiph.o: asiph.c spnbox.h extendedmatrix.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c asiph.c -avpr.o: avpr.c +avpr.o: avpr.c ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c avpr.c chkcons.o: chkcons.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h @@ -23,8 +23,14 @@ deallocation.o: deallocation.c spnbox.h ../pnheaders/matrix.h $(COMPILER) -c deallocation.c +dp.o: dp.c spnbox.h matrixmath.h extendendmatrix.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h + $(COMPILER) -c dp.c + extendedmatrix.o: extendedmatrix.c extendedmatrix.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c extendedmatrix.c + +fvpr.o: fvpr.c ../pnheaders/general.h ../pnheaders/matrix.h + $(COMPILER) -c fvpr.c ilpadm.o: ilpadm.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h $(COMPILER) -c ilpadm.c Modified: spnbox/admcon.c =================================================================== --- spnbox/admcon.c 2009-07-28 16:49:11 UTC (rev 209) +++ spnbox/admcon.c 2009-07-31 22:09:33 UTC (rev 210) @@ -347,7 +347,7 @@ } } /*Fill in d.*/ - for (i = 0; i < p->apCount; p++) + for (i = 0; i < p->apCount; i++) { SetMatrixEl(&DX, NumberOfRows(DX) - 1, p->apl[i], 1); } Modified: spnbox/asiph.c =================================================================== --- spnbox/asiph.c 2009-07-28 16:49:11 UTC (rev 209) +++ spnbox/asiph.c 2009-07-31 22:09:33 UTC (rev 210) @@ -259,8 +259,8 @@ newPlace matrix.*/ if (nullPlace) { - DeallocateMatrix(&data->newRow); - DeallocateMatrix(&data->newPlace); + if (data->newRow.type) DeallocateMatrix(&data->newRow); + if (data->newPlace.type) DeallocateMatrix(&data->newPlace); } /*Otherwise, we can go ahead and add to MT and NT.*/ else Modified: spnbox/deallocation.c =================================================================== --- spnbox/deallocation.c 2009-07-28 16:49:11 UTC (rev 209) +++ spnbox/deallocation.c 2009-07-31 22:09:33 UTC (rev 210) @@ -161,3 +161,11 @@ { FreeMemorySafe(data->l); } + +void DeallocateDp(dp_r *data) +{ + FreeMatrixSafe(&data->Lf); + FreeMemorySafe(data->Bf); + FreeMatrixSafe(&data->L0f); + FreeMemorySafe(data->B0f); +} Added: spnbox/dp.c =================================================================== --- spnbox/dp.c (rev 0) +++ spnbox/dp.c 2009-07-31 22:09:33 UTC (rev 210) @@ -0,0 +1,2171 @@ +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include "../pnheaders/general.h" +#include "../pnheaders/matrix.h" +#include "../pnheaders/pns.h" +#include "matrixmath.h" +#include "extendedmatrix.h" +#include "spnbox.h" + +typedef struct dpState +{ + unsigned dptype : 2; /*Type of supervision: 0 = deadlock prevention, 1 = + liveness enforcement, 2 = T-liveness enforcement.*/ + unsigned unique : 1; /*1 indicates a unique nonzero active subnet this + iteration?*/ + unsigned perm : 1; /*1 indicates successful siphon control.*/ + unsigned anetfail : 1; /*1 if the active subnet does not contain all + transitions in the net (DP and LE case) or all + transitions of T (T-LE case).*/ + unsigned incon : 1; /*1 if initial constraints exist.*/ + unsigned uncontro : 1; /*1 if uncontrollable and/or unobservable transitions + exist.*/ + unsigned usfl : 1; /*1 if redundant constraints have been eliminated.*/ + unsigned nolive : 1; /*1 if no liveness-enforcing supervisor exists.*/ + unsigned noTlive : 1; /*1 if no T-liveness-enforcing supervisor exists.*/ +} dpState; + +typedef struct dpData +{ + dpState state; + /*Various matrices*/ + matrix Dm, Dp, DI, Dcm, Dcp, L, L0, M; + /*Constraint-related vectors*/ + int *B, *B0, *G; + /*Maintain a count for G - it is not readily apparent what its count will be.*/ + int GCount; + /*Place lists:*/ + int *opl; /*Original places*/ + int *ipl; /*Independent places*/ + int *dpl; /*Dependent places*/ + int *apl; /*Active places*/ + int *upl; /*Useful places*/ + int *cpl; /*New control places added during a third-level sub-iteration.*/ + int *ExcludeT, *IncludeT; /*Transitions that must be included in or excluded + from use in subnet computation.*/ + int *TA; /*Active transitions.*/ + int *Tuc, *Tuo; /*Uncontrollable and unobservable transitions.*/ + + /*Counts of the list*/ + int opCount, ipCount, dpCount, apCount, upCount, cpCount, ExcludeCount, IncludeCount, TACount, TucCount, TuoCount; + + /*The size of the target Petri net.*/ + int targetRows, targetCols; + + /*TD is a list of lists, one for each transition, listing the indices of all + transitions that are unraisable if the key transition is dead. TDCount gives + the length of each list.*/ + int **TD; + int *TDCount; + + /*The log file pointers.*/ + FILE *log, *dat; + + /*Data related to primary processing runs*/ + int firstpass, restart, run, terminate; + char *status; + + /*Data used during the inner iterations.*/ + int iteration; //Iteration number + int uci, upd, consis; //flags + matrix TSIPH; //All siphons found during a run. + matrix S; //New siphons found during a run. +} dpData; + +/*A set of marking constraints. The return type of UpdateMarkingConstraints, +which concatenates the initial marking constraints with the ordinary marking +constraints.*/ +typedef struct MarkingConstraints +{ + matrix L; + int *B; +} MarkingConstraints; + +/*Functions used by dp, implemented in this file. See individual functions for +more information.*/ +static int CheckParams(dp_p *p); +static void Sort(int* array, int length); +static void AddToArray(int** array, int length, int item); +static void AddToCountedArray(int **array, int* length, int item); +static void AddToIndexArray(int** array, int* length, int item); +static void UpdateDPData(dpData *data, char* description, void *newData); +static MarkingConstraints UpdateMarkingConstraints(dpData *d); +static dpData CreateDpData(dp_p *p); +static void InitDpData(dp_p *p, dpData* d); +static void PrintMessage(dpData* d, char* message); +static void PrintState(dpData *d); +static void asbnmessage(dpData *d); +static void EnforceMarkingConstraints(dpData* d); +static void UpdateActiveNet(dpData* d); +static int ComputeSiphons(dpData* d); +static void PrintConstraints(dpData *d, matrix *l, int b, int *siphon, int cpl, int wn); +static void BuildSiphonConstraint(dpData* d, matrix* l, int* b, matrix* a, int *siphon); +static void AddSiphonExclusions(dpData* d, int* siphon); +static admcon_p BuildAdmconParams(dpData* d, int* siphon); +static int DoConstraintsApplyToAll(dpData *d, supervis_r* supervisRes, matrix* a, int* siphon); +static void CleanupSiphonChanges(dpData* d); +static void EnforceSiphonConstraints(dpData *d); +static void EnforceSiphonConstraints(dpData *d); +static void ReduceLB(dpData *d); +static char* ListTransitions(int* list, int listCount); +static void PrintConstraintSet(matrix* L, int* B, FILE* log); +static void FinalPrint(dpData* d); +static void FreeDpParts(dpData* d); + +dp_r dp(dp_p* params) +{ + dp_r result; + int i, j, flag; + memset(&result, 0, sizeof(dp_r)); + /*Check the parameters.*/ + if (! CheckParams(params)) + { + return result; + } + + /*Initialize the data structure.*/ + dpData d = CreateDpData(params); + + /*Initial message printing.*/ + if (is_verbose() >= VRB_DP) + { + switch(d.state.dptype) + { + case 0: + printf("Producing a deadlock prevention supervisor...\n"); + break; + case 1: + printf("Produceing a liveness enforcing supervisor...\n"); + break; + case 2: + printf("Producing a T-liveness enforcing supervisor...\n"); + break; + } + } + + /*Make sure the constraints are consistent: Get a set of complete constraints + and then check it using chkcons.*/ + MarkingConstraints cons = UpdateMarkingConstraints(&d); + if (cons.L.type) + { + chkcons_r chkconsRes = chkcons(&cons.L, cons.B, 0, 0); + /*If resCount is 0, it means the constraints are redundant.*/ + if (! chkconsRes.resCount) + { + if (d.log) + { + fprintf(d.log, "\n\nInconsistent set of constraints. Relax (L, B) and (L0, B0)."); + } + if (is_verbose() > VRB_DP) + { + printf("\n\nInconsistent set of constraints. Relax (L, B) and (L0, B0).\n"); + } + /*Mark for termination.*/ + d.terminate = 1; + } + DeallocateChkcons(&chkconsRes); + } + + /*Main processing begins here.*/ + while ((d.restart || d.firstpass) && ! d.terminate) + { + d.restart = 0; + if (++d.run > 1 && is_verbose() >= VRB_DP) + { + printf("\n ====================== RUN %d ========================\n",d.run); + } + + /*Setup the dp data for this run.*/ + InitDpData(params, &d); + + /*If there are marking constraints, enforce them.*/ + EnforceMarkingConstraints(&d); + + /*Build the useful places list: include all places initially.*/ + d.upCount = NumberOfRows(d.Dm); + d.upl = tcalloc(d.upCount, sizeof(int)); + for (i = 0; i < d.upCount; i++) + { + d.upl[i] = i; + } + + /*More log/verbose output output.*/ + if (d.log) + { + if (d.firstpass) + { + fprintf(d.dat, "\nStarting with the Petri net:"); + } + else + { + fprintf(d.dat, "\n ================= RUN NO. %d ================\n", d.run); + } + fflush(d.dat); + PrintState(&d); + } + if (is_verbose() >= VRB_DP) + { + asbnmessage(&d); + } + + /*Do an msplit.*/ + msplit_r msplitRes = msplit(&d.Dm, &d.Dp, 0, &d.M, &d.L0, &d.L, d.ipl, d.ipCount, d.dpl, d.dpCount, 0, 0); + UpdateDPData(&d, "free matrix Dm Dp M L0 L ipl ipCount free TD free intarray", &msplitRes); + + /*Update the listing of the active subnet.*/ + UpdateActiveNet(&d); + + /*Get ready for the inner iteration loop. Initialize TSIPH, the listing + of active siphons found this primary iteration, set the iteration number to + 1, and clear the uci flag.*/ + /*TSIPH should be initialized for column ops, as a siphon is recorded as + a column.*/ + if (d.TSIPH.type) DeallocateMatrix(&d.TSIPH); + AllocateMatrixType(2, &d.TSIPH, 0, NumberOfRows(d.Dm)); + TransposeMatrix(&d.TSIPH); + d.iteration = 1; + d.uci = 0; + + /*The inner iteration loop.*/ + while (! d.terminate) + { + /*Log and verbosity stuff.*/ + d.upd = 1; + if (d.log) + { + if (d.firstpass) fprintf(d.dat, "\nIteration %d", d.iteration); + else fprintf(d.dat, "\nRun %d, iterariont %d", d.run, d.iteration); + fflush(d.dat); + } + + /*Do the actual siphon computation. This function returns the number + of new siphons. If there were no new siphons, terminate the loop.*/ + if (! ComputeSiphons(&d)) break; + + /*Build constraints from the siphons and enforce them.*/ + EnforceSiphonConstraints(&d); + + /*Cleanup and finish applying the changes made to this point.*/ + CleanupSiphonChanges(&d); + d.iteration++; + } + d.firstpass = 0; + d.terminate = ! d.restart; + } + /*Bring the marking constraints down to target size.*/ + if (NumberOfColumns(d.L) - d.targetRows > 0) + { + RemoveColumns(&d.L, d.targetRows, NumberOfColumns(d.L) - d.targetRows, 2); + } + if (NumberOfColumns(d.L0) - d.targetRows > 0) + { + RemoveColumns(&d.L0, d.targetRows, NumberOfColumns(d.L0) - d.targetRows, 2); + } + + /*If there are any active transitions left, remove redundant constraints.*/ + if (d.TACount) + { + ReduceLB(&d); + } + + /*Build the result.*/ + result.Lf = d.L; + result.Bf = d.B; + result.L0f = d.L0; + result.B0f = d.B0; + result.how = d.status; + + /*Do log printing and closeout.*/ + if (d.log) + { + FinalPrint(&d); + fclose(d.log); + fclose(d.dat); + if (is_verbose() >= VRB_DP) + { + printf("\nOutput written to dp.log and dp.dat\n"); + } + } + + /*Free up other memory.*/ + FreeDpParts(&d); + + return result; +} + +/******************************************************************************* +FreeDpParts frees up parts of the dpData structure that are not being used as +part of the return value.*/ +void FreeDpParts(dpData* d) +{ + int i; + if (d->TD) + { + for (i = 0; i < NumberOfColumns(d->Dm); i++) + { + free(d->TD[i]); + } + free(d->TD); + } + DeallocateMatrix(&d->Dm); + DeallocateMatrix(&d->Dp); + DeallocateMatrix(&d->DI); + DeallocateMatrix(&d->Dcm); + DeallocateMatrix(&d->Dcp); + DeallocateMatrix(&d->M); + free(d->G); + free(d->opl); + free(d->ipl); + free(d->dpl); + free(d->apl); + free(d->upl); + free(d->cpl); + free(d->ExcludeT); + free(d->IncludeT); + free(d->TA); + free(d->Tuc); + free(d->Tuo); + free(d->TDCount); + DeallocateMatrix(&d->TSIPH); + DeallocateMatrix(&d->S); + memset(d, 0, sizeof(dpData)); +} + +/******************************************************************************* +FinalPrint prints the final data to the log and the data file.*/ +void FinalPrint(dpData* d) +{ + /*Generate a list that is the intersection of T and TA.*/ + int *TinTA; + int TinTACount = 0, i, j; + if (d->TACount && d->IncludeCount) + { + TinTA = tcalloc(d->TACount < d->IncludeCount ? d->TACount : d->IncludeCount, sizeof(int)); + for (i = 0, j = 0; i < d->TACount && j < d->IncludeCount; i++) + { + while(d->IncludeT[j] < d->TA[i]) j++; + if (d->IncludeT[j] == d->TA[i]) + { + TinTA[TinTACount++] = d->TA[i]; + } + } + } + /*flags*/ + int failed = ! strcmp(d->status, HOW_FAILED); + int impossible = ! strcmp(d->status, HOW_IMPOSSIBLE); + int ok = ! strcmp(d->status, HOW_OK); + char *achieve, *supname, *tmp;; + + fprintf(d->log, "\n\n===============================================================================\n\n"); + if (d->state.dptype == 0) + { + if (ok) + { + fprintf(d->log, "The generated supervisor is "); + if (d->state.perm && d->state.unique) + { + fprintf(d->log, "the least restrictive "); + if (d->state.anetfail) + { + fprintf(d->log, "T-"); + achieve = "T-live"; + } + else + { + achieve = "live"; + } + fprintf(d->log, "liveness enforcing supervisor."); + if (d->state.anetfail) + { + fprintf(d->log, "\nThe set T is:\nT = %s", ListTransitions(d->TA, d->TACount)); + } + } + else if (d->state.perm) + { + fprintf(d->log, "guaranteed to prevent total deadlock"); + achieve = "deadlock-free"; + if (d->state.anetfail) + { + fprintf(d->log, " in the subsystem containing the transitions\nT = %s", ListTransitions(d->TA, d->TACount)); + fprintf(d->log, "The supervisor may not enforce T-liveness.\n"); + fprintf(d->log, "The supervisor is guaranteed to be at least as permissive as the least\n"); + fprintf(d->log, "restrictive T-liveness enforcing supervisor."); + } + else + { + fprintf(d->log, "The supervisor may not enforce liveness.\n"); + fprintf(d->log, "The superviosr is guaranteed to be at least as permissive as the least\n"); + fprintf(d->log, "restrictive liveness enforcring supervisor"); + } + } + else + { + fprintf(d->log, "guaranteed to prevent total deadlock"); + achieve = "deadlock-free"; + if (d->state.anetfail) + { + fprintf(d->log, "in the subsystem containing the transitions\nT = %s", ListTransitions(d->TA, d->TACount)); + fprintf(d->log, "The supervisor may not enforce T-liveness.\n"); + } + else + { + fprintf(d->log, "the supervisor may not enforce liveness.\n"); + } + } + } + else if (impossible) + { + fprintf(d->log, "No deadlock prevention supervisors exist."); + if (d->state.incon && d->state.uncontro) + { + fprintf(d->log, "\nDeadlock prevention supervisors may exist for other initial constraints."); + } + else if (d->state.incon) + { + fprintf(d->log, "\nDeadlock prevention supervisors exist for other initial constraints."); + } + } + else if (failed) + { + fprintf(d->log, "The procedure could not generate a deadlock prevention supervisor."); + } + } + else + { + if (d->state.dptype == 1) + { + supname = "liveness"; + tmp = "live"; + } + else + { + supname = "T-liveness"; + tmp = "T-live"; + } + if (ok) + { + fprintf(d->log, "The generated supervisor is "); + if (d->state.unique && d->state.perm) + { + fprintf(d->log, "the least restrictive "); + if (d->state.anetfail) + { + fprintf(d->log, "Tx-liveness"); + achieve = "Tx-live"; + } + else + { + fprintf(d->log, "%s", supname); + achieve = tmp; + } + fprintf(d->log, " enforcing supervisor"); + if (d->state.anetfail) + { + fprintf(d->log, "The set Tx is:\nTx = %s", ListTransitions(d->TA, d->TACount)); + } + } + else if (d->state.perm) + { + fprintf(d->log, "guaranteed to enforce"); + if (d->state.anetfail) + { + fprintf(d->log, "Tx-liveness in the subsystem containing the transitions\n"); + fprintf(d->log, "Tx = %s", ListTransitions(TinTA, TinTACount)); + achieve = "Tx-live"; + } + else + { + fprintf(d->log, "%s, ", supname); + achieve = tmp; + } + fprintf(d->log, "and may not be the least restrictive"); + } + else if (d->state.unique) + { + fprintf(d->log, "\nThe supervisor is the least restrictive Ta-liveness "); + fprintf(d->log, "enforcing supervisor for\nTa = %s", ListTransitions(d->TA, d->TACount)); + } + if (d->state.nolive) + { + fprintf(d->log, "\nNo liveness enforcing supervisor exists."); + } + if (d->state.noTlive) + { + fprintf(d->log, "No T-livenss enforcing supervisor exists."); + } + } + else if (failed) + { + fprintf(d->log, "The procedure could not generate a liveness or T-liveness enforcing supervisor."); + } + else if (impossible) + { + fprintf(d->log, "No liveness/Tx-liveness enforcing supervisors exist, for any nonempty Tx."); + fprintf(d->log, "\nEven deadlock prevention is impossible."); + } + } + if (! ok) return; + switch(d->state.dptype) + { + case 0: + supname = "deadlock-free"; + break; + case 1: + supname = "live"; + break; + case 2: + supname = "T-live"; + break; + } + + if (! (NumberOfRows(d->L) && NumberOfRows(d->L0))) + { + fprintf(d->log, "\nNo constraints are needed: the Petri net is %s for all initial\nmarkings", supname); + } + else + { + if (NumberOfRows(d->L)) + { + fprintf(d->log, "\nThe supervisor is defined by the following constraints:\n"); + PrintConstraintSet(&d->L, d->B, d->log); + } + if (NumberOfRows(d->L0)) + { + if (NumberOfRows(d->L)) + { + fprintf(d->log, "\n\nIn addition to the inequalities above, the initial marking \"i\" must satisfy:\n"); + } + else + { + fprintf(d->log, "\n\nThe target Petri net is %s for all intiial markings \"i\" satisfying\n", achieve); + } + PrintConstraintSet(&d->L0, d->B0, d->log); + } + } + if (d->state.usfl) + { + fprintf(d->log, "\n\n(The redundant constraints have been eliminated.)"); + } + fflush(d->log); + free(TinTA); +} + +/******************************************************************************* +PrintConstraintSet prints the constraints represented by the matrix L and the +integer array B in pretty format to the file given.*/ +void PrintConstraintSet(matrix* L, int* B, FILE* log) +{ + int i; + matrix lrow; + AllocateMatrix(&lrow, 1, NumberOfColumns(*L)); + for (i = 0; i < NumberOfRows(*L); i++) + { + CopyBlock(1, NumberOfColumns(*L), L, i, 0, &lrow, 0, 0); + fprintf(log, "\n%s >= %d", avpr(&lrow, 0, DISPLAY_MATRIX, "m", 0), B[i]); + } + fflush(log); + DeallocateMatrix(&lrow); +} + +/******************************************************************************* +ListTransitions generates a pretty form of a transition index list.*/ +char* ListTransitions(int* list, int listCount) +{ + static char* buffer = 0; + static int bufferlength = 0; + char element[32]; + int i = 0, charsPerElement = 3, newbufferlength; + /*Compute the necessary buffer length.*/ + /*Take the log (to find the digit count) of the highest index.*/ + if (listCount) i = list[listCount - 1] + 1; + while (i) + { + charsPerElement++; + i /= 10; + } + if ((newbufferlength = charsPerElement * listCount + 4) > bufferlength) + { + free(buffer); + bufferlength = newbufferlength; + buffer = tcalloc(bufferlength, sizeof(char)); + } + + /*Fill the string.*/ + strcpy(buffer, "{"); + for (i = 0; i < listCount - 1; i++) + { + sprintf(element, "t%d, ", list[i]); + strcat(buffer, element); + } + if (listCount) + { + sprintf(element, "t%d", list[listCount - 1]); + strcat(buffer, element); + } + strcat(buffer, "}\n"); + return buffer; +} + +/******************************************************************************* +ReduceLB removes redundant constraints.*/ +void ReduceLB(dpData *d) +{ + MarkingConstraints cons = UpdateMarkingConstraints(d); + reduce_r rcons = reduce(&cons.L, cons.B); + free(cons.B); + DeallocateMatrix(&cons.L); + int i, j, k, count = 0; + /*We need to know which indices in the useful-places list returned by reduce + correspond to L rows and which correspond to L0 rows. Find the break.*/ + Sort(rcons.indf, NumberOfRows(rcons.Lf)); + for (count = 0; count < NumberOfRows(rcons.Lf) && rcons.indf[count] < NumberOfRows(d->L); count++); + /*The new marking constraint matrix will be all rows of the original that + are present in the list of useful rows returned by reduce. Remove all other + rows.*/ + j = NumberOfRows(d->L) - 1; + for (i = count - 1; i >= 0; i--) + { + while(j > rcons.indf[i]) + { + /*Remove the appropriate row from L.*/ + RemoveRows(&d->L, j, 1, -1); + /*Remove the appropriate entry from B.*/ + for (k = j; k < NumberOfRows(d->L); k++) + { + d->B[k] = d->B[k + 1]; + } + j--; + } + j--; + } + /*The new initial marking constraint will be all rows of the original that + are present in the list of useful rows returned by reduce. Remove all other + rows.*/ + j = NumberOfRows(d->L0) - 1; + for (i = NumberOfRows(rcons.Lf) - 1; i >= count; i--) + { + while(j > rcons.indf[i] - NumberOfRows(d->L)) + { + RemoveRows(&d->L0, j, 1, -1); + for (k = j; k < NumberOfRows(d->L0); k++) + { + d->B0[k] = d->B0[k + 1]; + } + j--; + } + j--; + } + /*Set the useful flag.*/ + d->state.usfl = (NumberOfRows(d->L) + NumberOfRows(d->L0) - NumberOfRows(rcons.Lf)) ? 1 : 0; + /*Free up memory used by the reduce-call result.*/ + DeallocateReduce(&rcons); +} + +/******************************************************************************* +EnforceSiphonConstraints creates and enforces new constraints based on the new +siphon lists.*/ +void EnforceSiphonConstraints(dpData *d) +{ + /*We will need several vectors with elements for each independent place. + Allocate space now.*/ + matrix l, l2, a; + AllocateMatrix(&a, 0, 0); + int siphon, i, j, k, b, x, flag, siphons; + int* currentSiphon; + /*Zero the (new) control place list.*/ + free(d->cpl); + d->cpl = 0; + d->cpCount = 0; + siphons = NumberOfColumns(d->S); + currentSiphon = tcalloc(NumberOfRows(d->S), sizeof(int)); + + /*Iterate through each new siphon.*/ + for (siphon = 0; siphon < siphons; siphon++) + { + /*Get a copy of the current siphon as an integer array.*/ + for (i = 0; i < NumberOfRows(d->S); i++) + { + currentSiphon[i] = GetMatrixEl(&d->S, i, siphon) ? 1 : 0; + } + AllocateMatrixType(2, &l, 1, d->ipCount); + DeallocateMatrix(&a); + AllocateMatrixType(1, &a, 1, NumberOfRows(d->Dm)); + + char message[64]; + /*Message printing.*/ + if (is_verbose() >= VRB_DP) + { + sprintf(message, "\nWorking on siphon %d of %d...", siphon + 1, NumberOfColumns(d->S)); + PrintMessage(d, message); + } + + /*Build a constraint based on this siphon.*/ + BuildSiphonConstraint(d, &l, &b, 0, currentSiphon); + + /*Check to see if the constraint is redundant.*/ + MarkingConstraints cons = UpdateMarkingConstraints(d); + chkcons_r chkconsRes; + + if (cons.L.type) + { + AddToArray(&cons.B, NumberOfRows(cons.L), b); + AllocateMatrixType(2, &l2, 1, NumberOfColumns(l)); + CopyMatrix(&l, &l2); + InsertRows(&cons.L, &l2, -1, -1); + chkconsRes = chkcons(&cons.L, cons.B, 0, 0); + } + else + { + /*If there are no constraints, then the proposed constraint is + nonredundant. Note this to be the case.*/ + memset(&chkconsRes, 0, sizeof(chkcons_r)); + chkconsRes.resCount = 1; + } + /*If res is not empty, the constraint is not redundant.*/ + if (chkconsRes.resCount) + { + DeallocateChkcons(&chkconsRes); + /*Build the admcon parameters.*/ + admcon_p admconP = BuildAdmconParams(d, currentSiphon); + /*Make the admcon call.*/ + admcon_r admconRes = admcon(&admconP); + /*Free the memory that was allocated for the admcon parameters.*/ + free(admconP.ntr); + + /*If admcon found an admissible constraint...*/ + if (admconRes.how) + { + /*Turn it into a constraint matrix and enforce it.*/ + for (i = 0; i < admconRes.lCount; i++) + { + SetMatrixEl(&a, 0, i, admconRes.l[i]); + } + supervis_r supervisRes = supervis(&d->Dp, &d->Dm, &l); + + /*Build l and b as before, but this time using a as the source.*/ + BuildSiphonConstraint(d, &l, &b, &a, 0); + /*Check the constraints if applicable.*/ + if (d->consis) + { + chkconsRes = chkcons(&cons.L, cons.B, &l, b); + } + else + { + memset(&chkconsRes, 0, sizeof(chkcons_r)); + chkconsRes.resCount = 1; + } + /*We want to find out if there exist any elements of the vector a such + that their zero/nonzero state is the opposite of that of the current + siphon.*/ + x = 0; + for (i = 0; i < NumberOfRows(d->S); i++) + { + if ((! GetMatrixEl(&d->S, i, siphon)) != (! GetMatrixEl(&a, i, 0))) + { + /*If such a place is encounted, set the generic variable x to 2 for + later use as a functon parameter.*/ + x = 2; + break; + } + } + /*If no such place existed, clear perm.*/ + if (! x) d->state.perm = 0; + + /*If the constraints were consistent, get ready to add them either to + L, B or L0, B0.*/ + if (chkconsRes.resCount) + { + /*Find out whether these constraints should apply to the marking at + all times or just to the initial marking.*/ + if (DoConstraintsApplyToAll(d, &supervisRes, &a, currentSiphon)) + { + /*Print constraint data.*/ + if (d->log) PrintConstraints(d, &l, b, currentSiphon, NumberOfRows(d->Dm) - 1, x); + /*Add the new place index to the dependent place list, the useful + places list, and the new control places list.*/ + AddToIndexArray(&d->dpl, &d->dpCount, NumberOfRows(supervisRes.Dfm) - 1); + AddToIndexArray(&d->upl, &d->upCount, NumberOfRows(supervisRes.Dfm) - 1); + AddToIndexArray(&d->cpl, &d->cpCount, NumberOfRows(supervisRes.Dfm) - 1); + /*Dm and Dp should be set to the supervised net Dfm and Dfp.*/ + UpdateDPData(d, "Dm Dp", &supervisRes); + memset(&supervisRes, 0, sizeof(supervis_r)); + /*Add to the constraints. Make a copy of l first so that we can do + optimized row-adds and not do too many allocations.*/ + AddToArray(&d->B, NumberOfRows(d->L), NumberOfRows(d->L)); + AddToCountedArray(&d->G, &d->GCount, NumberOfRows(d->L)); + AllocateMatrixType(2, &l2, 1, NumberOfColumns(l)); + CopyMatrix(&l, &l2); + AddToArray(&d->B, NumberOfRows(d->L), b); + AddToCountedArray(&d->G, &d->GCount, b); + InsertRows(&d->L, &l, -1, 1); + InsertRows(&d->M, &l2, -1, 1); + /*Add a null column to the end of S. */ + InsertNullColumns(&d->S, -1, 1, -1); + } + else + { + /*Add the built constraint to the initial marking constraints.*/ + if (d->log) PrintConstraints(d, &l, b, currentSiphon, 0, x); + AddToArray(&d->B0, NumberOfRows(d->L0), NumberOfRows(d->L0)); + InsertRows(&d->L0, &l, -1, 1); + } + } + else + { + /*If the constraints were redundant, just do a constraint printing + with no new constraints. Also deallocate l.*/ + DeallocateMatrix(&l); + if (d->log) PrintConstraints(d, 0, 0, currentSiphon, -1, x); + d->upd = 0; + /*Add some indices to X: those transitions such that they have nonzero + output arcs from at least one of the places in the current siphon.*/ + AddSiphonExclusions(d, currentSiphon); + d->state.perm = d->state.perm > 1 ? 2 : 0; + d->restart = 1; + d->terminate = 1; + } + /*Deallocate the supervis result if it still needs to be deallocated.*/ + DeallocateSupervis(&supervisRes); + } + else + { + /*If admcon could not find admissible constraints, add to the excluded + transition list in the same way we did earlier.*/ + AddSiphonExclusions(d, currentSiphon); + d->uci = 1; + d->state.perm = 0; + d->upd = 0; + if (d->log) PrintConstraints(d, 0, 0, 0, -2, 1); + } + DeallocateAdmcon(&admconRes); + } + else + { + if (d->log) PrintConstraints(d, 0, 0, 0, -1, 0); + } + } +} + +/******************************************************************************* +CleanupSiphonChanges is a subroutine of EnforceSiphonConstraints. It performs a +transition split and an eac-net conversion on the net, then updates the active +subnet listing.*/ +void CleanupSiphonChanges(dpData* d) +{ + int i, j, k; + + + /*Transition split.*/ + msplit_r msplitRes = msplit(&d->Dm, &d->Dp, 0, &d->M, &d->L0, &d->L, d->ipl, d->ipCount, d->dpl, d->dpCount, d->TD, d->TDCount); + UpdateDPData(d, "free matrix Dm Dp M L0 L ipl ipCount TD TDCount", &msplitRes); + + /*If we are doing any kind of liveness enforcement, convert the net to an + eac-net.*/ + if (d->state.dptype) + { + /*We need a flag array for the new control places.*/ + int *ncp = tcalloc(NumberOfRows(d->Dm), sizeof(int)); + for (i = 0; i < d->cpCount; i++) + { + ncp[d->cpl[i]] = 1; + } + + pn2eacpn_r pn2eacpnRes = pn2eacpn(&d->Dm, &d->Dp, ncp, &d->M, &d->L0, &d->L, d->ipl, d->ipCount, d->dpl, d->dpCount, d->TD, d->TDCount); + UpdateDPData(d, "free matrix Dm Dp M L0 L ipl ipCount TD TDCount", &pn2eacpnRes); + + free(ncp); + } + + tactn_r tactnRes; + actn_r actnRes; + /*Update the active subnet.*/ + if (is_verbose() >= VRB_DP) + { + PrintMessage(d, "Updating the active subnet..."); + } + if (d->state.dptype) + { + if (d->upd) + { + tactnRes = tactn(&d->Dm, &d->Dp, d->IncludeT, d->IncludeCount, d->ExcludeT, d->ExcludeCount, &d->Dcm, &d->Dcp, 0); + UpdateDPData(d, "Dcm Dcp free matrix free matrix TA TACount", &tactnRes); + } + else + { + tactnRes = tactn(&d->Dm, &d->Dp, d->IncludeT, d->IncludeCount, d->ExcludeT, d->ExcludeCount, 0, 0, 1); + d->state.unique = tactnRes.unique; + UpdateDPData(d, "Dcm Dcp free matrix free matrix TA TACount", &tactnRes); + } + } + else + { + if (d->upd) + { + actnRes = actn(&d->Dm, &d->Dp, d->ExcludeT, d->ExcludeCount, &d->Dcm, &d->Dcp, 1, 0); + UpdateDPData(d, "Dcm Dcp free matrix free matrix TA TACount", &actnRes); + } + else + { + actnRes = actn(&d->Dm, &d->Dp, d->ExcludeT, d->ExcludeCount, &d->Dcm, &d->Dcp, 0, 1); + d->state.unique = actnRes.unique; + UpdateDPData(d, "Dcm Dcp free matrix free matrix TA TACount", &actnRes); + } + } + /*Update the exclusion list. It should include all transitions which are + inactive. We can build this list from the active transition list already + computed.*/ + free(d->ExcludeT); + d->ExcludeCount = NumberOfColumns(d->Dm) - d->TACount; + if (d->ExcludeCount) + { + d->ExcludeT = tcalloc(d->ExcludeCount, sizeof(int)); + j = 0; + k = 0; + for (i = 0; i < d->TACount; i++) + { + while (j < d->TA[i]) + { + d->ExcludeT[k++] = j++; + } + j++; + } + } + else + { + d->ExcludeT = 0; + } + /*If there are no active transitions, set failure and termination flags.*/ + if (! d->TACount) + { + d->terminate = 1; + d->restart = 0; + d->status = HOW_FAILED; + if (d->firstpass && (! d->uci) && ((! d->state.dptype) || d->state.unique)) + { + d->status = HOW_IMPOSSIBLE; + } + } + /*Update the useful places list. It should be all independent places with + indices valid for the target net and all dependent places.*/ + if (d->upd) + { + /*Find the number of independent places to use.*/ + for (i = 0; i < d->ipCount; i++) + { + if (d->ipl[i] > d->targetRows) break; + } + /*i now contains the number of independent places that we want to use. + Update the total count and allocate memory.*/ + free(d->upl); + d->upCount = i + d->dpCount; + d->upl = tcalloc(d->upCount, sizeof(int)); + /*Fill in the independent places.*/ + for (j = 0; j < i; j++) + { + d->upl[j] = d->ipl[j]; + } + /*Fill in the dependent places*/ + for (j = 0; j < d->dpCount; j++) + { + d->upl[i + j] = d->dpl[j]; + } + /*Sort the list.*/ + if (d->upCount) Sort(d->upl, d->upCount); + } +} + +/******************************************************************************* +DoConstraintsApplyToAll is a subroutine of EnforceSiphonConstraints. It +determines if a set of constraints generated in an admcon call should be added +as constraints on marking at any time or only on initial marking. It returns +nonzero to indicate the former and zero to indicate the latter.*/ +int DoConstraintsApplyToAll(dpData *d, supervis_r* supervisRes, matrix* a, int *siphon) +{ + int flag = 0, i, j; + /*Iterate through transitions*/ + for (i = 0; i < NumberOfColumns(supervisRes->Dfm); i++) + { + /*Is there an output arc from the new place and no input arc to the + new place?*/ + if (GetMatrixEl(&supervisRes->Dfm, NumberOfRows(supervisRes->Dfm) - 1, i) && ! GetMatrixEl(&supervisRes->Dfp, NumberOfRows(supervisRes->Dfp) - 1, i)) + { + /*Check to make sure there are no input arcs to any transitions in + the siphon.*/ + for (j = 0; j < NumberOfRows(d->S); j++) + { + if (GetMatrixEl(&supervisRes->Dfp, j, i)) break; + } + /*If there were none, set the flag and break out of the loop.*/ + if (j == NumberOfRows(d->S)) + { + flag = 1; + break; + } + } + } + /*If the flag has no yet been set, it may be set if there are any + elements of a such that they are not equal to the corresponding + elements in the current siphon.*/ + if (! flag) + { + for (i = 0; i < NumberOfColumns(*a); i++) + { + if (GetMatrixEl(a, 0, i) != siphon[i]) + { + flag = 1; + break; + } + } + } + return flag; +} + +/******************************************************************************* +BuildAdmconParams is a subroutine of EnforceSiphonConstraints. It fills an +admcon_p structure with the parameters necessary to make the admcon call.*/ +admcon_p BuildAdmconParams(dpData* d, int* siphon) +{ + /*We'll need an updated copy of the active place list. Build it now.*/ + int *newApl = tcalloc(NumberOfRows(d->Dcm), sizeof(int)); + int newApCount = 0, i, j; + for (i = 0; i < NumberOfRows(d->Dcm); i++) + { + for (j = 0; j < NumberOfColumns(d->Dcm); j++) + { + if (GetMatrixEl(&d->Dcm, i, j) || GetMatrixEl(&d->Dcp, i, j)) + { + break; + } + } + if (j == NumberOfColumns(d->Dcm)) newApl[newApCount++] = i; + } + free(d->apl); + d->apl = newApl; + d->apCount = newApCount; + + /*Transform the siphon row to an admissible constraint using admcon. + Start by building the admcon call parameters:*/ + admcon_p admconP; + /*Most of the parameters come straight from the problem data.*/ + admconP.siphon = siphon; + admconP.Dm = d->Dm; + admconP.Dp = d->Dp; + admconP.DI = d->DI; + admconP.ipl = d->ipl; + admconP.dpl = d->dpl; + admconP.opl = d->opl; + admconP.apl = d->apl; + admconP.Tuc = d->Tuc; + admconP.Tuo = d->Tuo; + admconP.ipCount = d->ipCount; + admconP.dpCount = d->dpCount; + admconP.opCount = d->opCount; + admconP.apCount = d->apCount; + admconP.TucCount = d->TucCount; + admconP.TuoCount = d->TuoCount; + /*For ntr, we build a list of all transitions not part of the original + matrix.*/ + if (NumberOfColumns(d->Dm) - d->targetCols) + { + admconP.ntCount = NumberOfColumns(d->Dm) - d->targetCols; + admconP.ntr = tcalloc(admconP.ntCount, sizeof(int)); + for (i = d->targetCols; i < NumberOfColumns(d->Dm); i++) + { + admconP.ntr[i - d->targetCols] = i; + } + } + else + { + admconP.ntCount = 0; + admconP.ntr = 0; + } + /*We know these parameters are well formed. Skip the (time-consuming) + parameter check.*/ + admconP.skipParamCheck = 1; + return admconP; +} + +/******************************************************************************* +AddSiphonExclusions is called as a subroutine of EnforceSiphonConstraints. It +is used under certain circumstances when a siphon does not result in an +admissible constraint set. It adds to the excluded transition list those +transitions such that they have nonzero output arcs from at least one of the +places in the current siphon.*/ +void AddSiphonExclusions(dpData* d, int* siphon) +{ + /*Build a flag array to indicate the transitions we'll have to add.*/ + int *ExcludeFlag = tcalloc(NumberOfColumns(d->Dm), sizeof(int)); + int i, j, k; + for (i = 0; i < d->ExcludeCount; i++) + { + ExcludeFlag[d->ExcludeT[i]] = 1; + } + /*Find the new transitions.*/ + k = d->ExcludeCount; + for (j = 0; j < NumberOfColumns(d->Dm); j++) + { + for (i = 0; i < NumberOfRows(d->S); i++) + { + if (GetMatrixEl(&d->Dm, i, j) && ! (siphon[i] || ExcludeFlag[i])) + { + ExcludeFlag[i] = 1; + k++; + } + } + } + /*Now convert the flag array to an index list. Use the same memory; + this is a waste of memory but avoids an allocation.*/ + free(d->ExcludeT); + d->ExcludeCount = k; + d->ExcludeT = ExcludeFlag; + k = 0; + for (i = 0; i < NumberOfColumns(d->Dm); i++) + { + if (d->ExcludeT[i]) d->ExcludeT[k++] = i; + } +} + +/******************************************************************************* +BuildSiphonConstraint is called as a subroutine of EnforceSiphonConstraints. It +builds a single constraint (a row vector and a constant) based on either the row +vector in matrix form in a or the row vector in array form in siphon. It will +use a if it is present (pointer is non-null).*/ +void BuildSiphonConstraint(dpData *d, matrix* l, int* b, matrix* a, int *siphon) +{ + int i, j; + /*Build a constraint row (l and b) ignoring M.*/ + for (i = 0; i < d->ipCount; i++) + { + SetMatrixEl(l, 0, i, a ? GetMatrixEl(a, 0, d->ipl[i]) : siphon[d->ipl[i]]); + } + *b = 1; + /*Take into account M if it exists.*/ + if (d->M.type && NumberOfRows(d->M) && NumberOfColumns(d->M)) + { + /*Add to each element of l the matrix product of the rows of the siphon + corresponding to dependent places and the transformation matrix M. The + siphon matrix is all 1s and 0s, so we can skip actual multiplication and + just do a test for zero.*/ + for (i = 0; i < NumberOfColumns(d->M); i++) + { + for (j = 0; j < d->dpCount; j++) + { + if (a ? GetMatrixEl(a, 0, d->dpl[j]) : siphon[d->dpl[j]]) + { + SetMatrixEl(l, 0, i, GetMatrixEl(l, 0, i) + GetMatrixEl(&d->M, j, i)); + } + } + } + /*Add to b the matrix product of the column vector G (transposed) and those + elements of the current siphon which correspond to dependent places. Again, + we don't have to actually multiply but merely test for nonzero.*/ + for (i = 0; i < d->dpCount; i++) + { + if (a ? GetMatrixEl(a, 0, d->dpl[i]) : siphon[d->dpl[i]]) *b += d->G[i]; + } + } +} +/******************************************************************************* +This functions prints constraints to the log files during the building and +enforcement of constraints based on siphons.*/ +void PrintConstraints(dpData *d, matrix *l, int b, int *siphon, int cpl, int wn) +{ + int i; + /*Print the siphon*/ + fprintf(d->log, "\nSiphon %s", fvpr(siphon, NumberOfRows(d->S), DISPLAY_INTS, 2)); + switch(cpl) + { + case 0: + /*Display.*/ + fprintf(d->log, "\nNo control places needed. Constraints below added to (L0, B0)"); + fprintf(d->log, "\n%s >= %d", avpr(l, NumberOfColumns(*l), DISPLAY_MATRIX, 0, 0), b); + break; + case -1: + fprintf(d->log, "\nNo constraints added."); + break; + case -2: + fprintf(d->log, "\nInadmissible constraint."); + break; + default: + fprintf(d->log, "\nPlace %d added to control the siphon and enforce:", cpl); + fprintf(d->log, "\n%s >= %d", avpr(l, NumberOfColumns(*l), DISPLAY_MATRIX, 0, 0), b); + break; + } + if (wn == 1) fprintf(d->log, "\nSiphon control failure occurred."); + else if (wn == 2) fprintf(d->log, "\nSuboptimal admissibility transformation."); + fprintf(d->log, "\n"); + fflush(d->log); +} + +/******************************************************************************* +ComputeSiphons finds the minimal active siphons for an iteration. It returns the +number of new siphons.*/ +int ComputeSiphons(dpData* d) +{ + /*A status message.*/ + if (is_verbose() > VRB_DP) + { + PrintMessage(d, "Computing the minimal active siphons..."); + } + + /*We'll needs lists of active transitions and places. TA will have just been + updated before this function call. Update apl. To avoid having to iterate + through the whole matrix twice, preallocate newApl to its maximum possible + size.*/ + int *newApl = tcalloc(NumberOfRows(d->Dcm), sizeof(int)); + int newApCount = 0, i, j; + for (i = 0; i < NumberOfRows(d->Dcm); i++) + { + for (j = 0; j < NumberOfColumns(d->Dcm); j++) + { + if (GetMatrixEl(&d->Dcm, i, j) || GetMatrixEl(&d->Dcp, i, j)) + { + break; + } + } + if (j == NumberOfColumns(d->Dcm)) newApl[newApCount++] = i; + } + free(d->apl); + d->apl = newApl; + d->apCount = newApCount; + + /*Build a list of places that will be considered for siphon computation. This + is any place such that it is present in both the useful and the active place + lists.*/ + int* possibleSiphons = tcalloc(d->apCount < d->upCount ? d->apCount : d->upCount, sizeof(int)); + int possibleSiphonCount = 0; + j = 0; + for (i = 0; i < d->apCount && j < d->upCount; i++) + { + while (j < d->upCount && d->upl[j] < d->apl[i]) j++; + if (j < d->upCount && d->upl[j] == d->apl[i]) + { + possibleSiphons[possibleSiphonCount++] = d->apl[i]; + } + } + + /*Make sure TSIPH is the right size.*/ + if (NumberOfRows(d->TSIPH) < NumberOfRows(d->Dm)) + { + InsertNullRows(&d->TSIPH, NumberOfRows(d->Dm) - NumberOfRows(d->TSIPH), -1, -1); + } + /*Remove any columns from TSIPH such that they have no nonzero entries in rows + corresponding to active places.*/ + j = 0; + while (j < NumberOfColumns(d->TSIPH)) + { + for (i = 0; i < d->apCount; i++) + { + if (GetMatrixEl(&d->TSIPH, d->apl[i], j)) break; + } + if (i == d->apCount) + { + RemoveColumns(&d->TSIPH, j, 1, -1); + } + else + { + j++; + } + } + + /*Minimal active siphon computation.*/ + asiph_r asiphRes = asiph(&d->Dm, &d->Dp, possibleSiphons, possibleSiphonCount, &d->TSIPH, &d->Dcm, &d->Dcp); + UpdateDPData(d, "TSIPH S", &asiphRes); + + /*Remove from the new siphons list those siphons which contain no useful + places.*/ + j = 0; + while (j < NumberOfColumns(d->S)) + { + for (i = 0; i < d->upCount; i++) + { + if (GetMatrixEl(&d->S, d->upl[i], j)) break; + } + if (d->upCount == i) + { + RemoveColumns(&d->S, j, 1, -1); + } + else + { + j++; + } + } + + /*Get the new siphon count.*/ + int newSiphons = NumberOfColumns(d->S); + + /*Make sure that ll the new siphons are in fact siphons.*/ + issiph_r issiphRes = issiph(&d->Dm, &d->Dp, &d->S, 1); + + if (issiphRes.flx) + { + DeallocateIssiph(&issiphRes); + merror(0, "Siphon Computation Error"); + } + + DeallocateIssiph(&issiphRes); + + /*Do printing.*/ + if (d->log) + { + if (d->firstpass) + { + fprintf(d->log, "\nIteration %d - %d new minimum siphons", d->iteration, newSiphons); + } + else + { + fprintf(d->log, "\nRun %d, iteration %d - %d new minimum siphons", d->run, d->iteration, newSiphons); + } + PrintState(d); + fflush(d->log); + } + return newSiphons; +} + +/******************************************************************************* +UpdateActiveNet updates the active subnet as appropriate for the type of +enforcement we are doing.*/ +void UpdateActiveNet(dpData* d) +{ + int i, j, flag; + if (d->state.dptype) + { + /*If we get here we are doing (T-)liveness enforcement. + Transform the net to an EAC net.*/ + pn2eacpn_r pn2eacpnRes = pn2eacpn(&d->Dm, &d->Dp, 0, &d->M, &d->L0, &d->L, d->ipl, d->ipCount, d->dpl, d->dpCount, d->TD, d->TDCount); + UpdateDPData(d, "free matrix Dm Dp M L0 L ipl ipCount TD TDCount", &pn2eacpnRes); + + /*Find the t-minimal active subnet.*/ + tactn_r tactnRes = tactn(&d->Dm, &d->Dp, d->IncludeT, d->IncludeCount, d->ExcludeT, d->ExcludeCount, 0, 0, 1); + d->state.unique = tactnRes.unique; + UpdateDPData(d, "Dcm Dcp free matrix free matrix TA TACount", &tactnRes); + + /*Check to make sure that all required transitions are present in the + subnet. We assume that TA and IncludeT entries have been properly sorted, + from lowest to highest. Let i be the index in IncludeT and j be the index + in TA.*/ + j = 0; + flag = ! d->TACount; + for (i = 0; i < d->IncludeCount && ! flag; i++) + { + while(j < d->TACount - 1 && d->TA[j] < d->IncludeT[i]) j++; + if (d->TA[j] != d->IncludeT[i]) + { + flag = 1; + break; + } + } + if (flag) + { + d->state.anetfail = 1; + if (d->firstpass) + { + if (d->state.dptype == 2) d->state.noTlive = 1; + else d->state.nolive = 1; + } + } + } + else + { + /*If we get here, we are doing deadlock prevention, not (T-)liveness + enforcement. Begin with active subnet finding.*/ + actn_r actnRes = actn(&d->Dm, &d->Dp, d->ExcludeT, d->ExcludeCount, 0, 0, 0, 1); + d->state.unique = actnRes.unique; + UpdateDPData(d, "Dcm Dcp free matrix free matrix TA TACount", &actnRes); + /*Same test as above - make sure that all required transitions are + present in the active subnet.*/ + j = 0; + flag = ! d->TACount; + for (i = 0; i < d->IncludeCount && ! flag; i++) + { + while(j < d->TACount - 1 && d->TA[j] < d->IncludeT[i]) j++; + if (d->TA[j] != d->IncludeT[i]) + { + flag = 1; + break; + } + } + if (flag) + { + d->state.anetfail = 1; + } + } + /*Check to see if the task is impossible.*/ + if (! d->TACount) + { + d->terminate = 1; + if (d->firstpass) + { + d->status = HOW_IMPOSSIBLE; + } + else + { + d->status = HOW_FAILED; + } + d->state.incon = 0; + } +} + +/******************************************************************************* +EnforceMarkingConstraints enforces the present marking constraints on the net.*/ +void EnforceMarkingConstraints(dpData* d) +{ + if (NumberOfRows(d->L)) + { + supervis_r supervisRes = supervis(&d->Dp, &d->Dm, &d->L); + UpdateDPData(d, "Dm Dp", &supervisRes); + /*Create the dependent place list.*/ + d->dpCount = NumberOfRows(d->Dm) - d->targetRows; + d->dpl = tcalloc(d->dpCount, sizeof(int)); + int i; + for (i = d->targetRows; i < NumberOfRows(d->Dm); i++) + { + d->dpl[i - d->targetRows] = i; + } + /*Setup M = L, G = B. Optimize for row operations.*/ + AllocateMatrixType(2, &d->M, NumberOfRows(d->L), NumberOfColumns(d->L)); + CopyMatrix(&d->L, &d->M); + d->G = tcalloc(NumberOfRows(d->L), sizeof(int)); + memcpy(d->G, d->B, NumberOfRows(d->L) * sizeof(int)); + d->GCount = NumberOfRows(d->L); + } +} + +/******************************************************************************* +asbnmessage prints a per-major-iteration message.*/ +void asbnmessage(dpData *d) +{ + if (d->run < 2) + { + printf("\nI"); + } + else + { + printf("\nRun %d, i", d->run); + } + if (d->state.dptype < 2) + { + printf("teration 1: Computing the maximal active subnet...\n"); + } + else + { + printf("teration 1: Computing a T-minimal active subnet...\n"); + } +} + +/******************************************************************************* +This function prints the current state to the data and log files.*/ +void PrintState(dpData *d) +{ + fprintf(d->log, "\nThe Petri net has %d places and %d transitions", NumberOfRows(d->Dm), NumberOfColumns(d->Dm)); + if (d->ExcludeT) fprintf(d->log, "\nThe current active subnet excludes the transitions %s", fvpr(d->ExcludeT, d->ExcludeCount, DISPLAY_INTS, 2)); + + int i, j; + /*Build a list of the original places for vector display.*/ + if (d->targetRows) + { + int *originalPlaces = tcalloc(d->targetRows, sizeof(int)); + for (i = 1; i < d->targetRows; i++) + { + originalPlaces[i] = i; + } + /*Display it.*/ + fprintf(d->log, "\n %d original places: %s", d->targetRows, fvpr(originalPlaces, d->targetRows, DISPLAY_INTS, 2)); + free(originalPlaces); + } + + /*We need a list of all the dependent and independent places that have been + added so far, that is, all those with indices greater than the maximum present + in the original net.*/ + int firstNewInd = -1, firstNewDep = -1; + for (i = 0; i < d->ipCount; i++) + { + if (d->ipl[i] > d->targetRows) + { + firstNewInd = i; + break; + } + } + for (i = 0; i < d->dpCount; i++) + { + if (d->dpl[i] > d->targetRows) + { + firstNewDep = i; + break; + } + } + if (firstNewInd != -1) + { + if (d->ipCount - firstNewInd == 1) + { + fprintf(d->log, "\n One split place: %s", fvpr(d->ipl + firstNewInd, d->ipCount - firstNewInd, DISPLAY_INTS, 2)); + } + else if (d->ipCount - firstNewInd > 1) + { + fprintf(d->log, "\n %d split places: %s", d->ipCount - firstNewInd, fvpr(d->ipl + firstNewInd, d->ipCount - firstNewInd, DISPLAY_INTS, 2)); + } + } + if (firstNewDep != -1) + { + if (d->dpCount - firstNewDep == 1) + { + fprintf(d->log, "\n One control place: %s", fvpr(d->dpl + firstNewDep, d->dpCount - firstNewDep, DISPLAY_INTS, 2)); + } + else if (d->dpCount - firstNewDep > 1) + { + fprintf(d->log, "\n %d control places: %s", d->dpCount - firstNewDep, fvpr(d->dpl + firstNewDep, d->dpCount - firstNewDep, DISPLAY_INTS, 2)); + } + } + fprintf(d->log, "\n"); + + /*We want to display a modified version of M - one with null columns in place + for each of the non-independent places, so that it has a column for each + column of the net. Do this one row at a time. Allocate the row.*/ + int *MRow = tcalloc(NumberOfRows(d->Dm), sizeof(int)); + for (i = 0; i < NumberOfRows(d->M); i++) + { + memset(MRow, 0, sizeof(int) * NumberOfRows(d->Dm)); + for (j = 0; j < d->ipCount; j++) + { + MRow[d->ipl[j]] = GetMatrixEl(&d->M, i, j); + } + /*Display the row.*/ + fprintf(d->log, "\n %d --> %s >= %d", d->dpl[i], avpr(MRow, NumberOfRows(d->Dm), DISPLAY_INTS, 0, 0)); + } + free(MRow); + + /*Build a Petri net object we can use with displaypn to print the current net + to the dat file.*/ + pns currentPn = createpn("mDm mDp", d->Dm, d->Dp); + /*Do the display.*/ + fprintf(d->dat, "\n"); + displaypn(currentPn, d->dat); + fprintf(d->dat, "\n"); + deallocpn(¤tPn); + fflush(d->log); + fflush(d->dat); +} + +/******************************************************************************* +This function prints a status message with information about current run and +iteration.*/ +void PrintMessage(dpData* d, char* message) +{ + if (d->iteration > 0) + { + if (d->run < 2) + { + printf("Iteration %d: %s\n", d->iteration, message); + } + else + { + printf("Run %d, iteration %d: %s\n", d->run, d->iteration, message); + } + } + else + { + printf("%s\n", message); + } +} + +/******************************************************************************* +This function modifies the dpData structure passed to it to set it up for a +single run. It examines the firstpass bit to determine whether or not certain +matrices have already been set up correctly.*/ +void InitDpData(dp_p *p, dpData* d) +{ + /*If this is the first pass, then the matrices have been properly initialized. + Otherwise, make them new copies of the original parameter matrices.*/ + if (! d->firstpass) + { + DeallocateMatrix(&d->Dm); + AllocateMatrixType(2, &d->Dm, NumberOfRows(p->Dm), NumberOfColumns(p->Dm)); + CopyMatrix(&p->Dm, &d->Dm); + DeallocateMatrix(&d->Dp); + AllocateMatrixType(2, &d->Dp, NumberOfRows(p->Dp), NumberOfColumns(p->Dp)); + CopyMatrix(&p->Dp, &d->Dp); + /*If either of the constraint matrices is not present, initialize it to have + the right number of columns and zero rows so that it can be concatenated with + the other to form the total constraint matrix.*/ + if (p->L.type) + { + DeallocateMatrix(&d->L); + AllocateMatrixType(2, &d->L, NumberOfRows(p->L), NumberOfColumns(p->L)); + CopyMatrix(&p->L, &d->L); + } + else + { + DeallocateMatrix(&d->L); + AllocateMatrixType(2, &d->L, 0, NumberOfRows(p->Dm)); + } + if (p->L0.type) + { + DeallocateMatrix(&d->L0); + AllocateMatrixType(2, &d->L0, NumberOfRows(p->L0), NumberOfColumns(p->L0)); + CopyMatrix(&p->L0, &d->L0); + } + else + { + DeallocateMatrix(&d->L0); + AllocateMatrixType(2, &d->L0, 0, NumberOfRows(p->Dm)); + } + if (p->B) + { + free(d->B); + d->B = tcalloc(NumberOfRows(d->L), sizeof(int)); + memcpy(d->B, p->B, NumberOfRows(d->L) * sizeof(int)); + } + if (p->B0) + { + free(d->B0); + d->B0 = tcalloc(NumberOfRows(d->L0), sizeof(int)); + memcpy(d->B0, p->B0, NumberOfRows(d->L0) * sizeof(int)); + } + } + + /*Initialize the original, independent, and dependent place lists.*/ + d->opCount = d->targetRows; + d->ipCount = d->targetRows; + d->dpCount = 0; + if (d->opl) free(d->opl); + if (d->ipl) free(d->ipl); + if (d->dpl) free(d->dpl); + d->opl = tcalloc(d->opCount, sizeof(int)); + d->ipl = tcalloc(d->ipCount, sizeof(int)); + d->dpl = 0; + int i; + for (i = 0; i < d->targetRows; i++) + { + d->opl[i] = i; + d->ipl[i] = i; + } + + /*Empty G and M.*/ + if (d->G) free(d->G); + if (d->M.type) DeallocateMatrix(&d->M); + + /*Initialize M to be the right size for an msplit.*/ + AllocateMatrix(&d->M, 0, d->targetRows); + + /*Remove from the exclusion list any transitions beyond those of the original + matrices. This can be done by finding the index of the first list element that + is too high and marking this as the list length.*/ + for (i = 0; i < d->ExcludeCount; i++) + { + if (d->ExcludeT[i] > d->targetCols) break; + } + d->ExcludeCount = i; + d->state.perm = 1; + d->status = HOW_OK; +} + +/******************************************************************************* +This function fills in the dpData structure containing information for a dp run +prior to the first run.*/ +dpData CreateDpData(dp_p *p) +{ + dpData d; + memset(&d, 0, sizeof(dpData)); + /*Copy matrices*/ + AllocateMatrixType(2, &d.Dm, NumberOfRows(p->Dm), NumberOfColumns(p->Dm)); + CopyMatrix(&p->Dm, &d.Dm); + AllocateMatrixType(2, &d.Dp, NumberOfRows(p->Dp), NumberOfColumns(p->Dp)); + CopyMatrix(&p->Dp, &d.Dp); + /*Get the target matrix DI.*/ + d.DI = SubtractMatrix(&d.Dp, &d.Dm, (matrix*) 2); + int i; + + /*If either of the constraint matrices is not present, initialize it to have + the right number of columns and zero rows so that it can be concatenated with + the other to form the total constraint matrix.*/ + if (p->L.type) + { + AllocateMatrixType(2, &d.L, NumberOfRows(p->L), NumberOfColumns(p->L)); + CopyMatrix(&p->L, &d.L); + } + else + { + AllocateMatrixType(2, &d.L, 0, NumberOfRows(p->Dm)); + } + if (p->L0.type) + { + AllocateMatrixType(2, &d.L0, NumberOfRows(p->L0), NumberOfColumns(p->L0)); + CopyMatrix(&p->L0, &d.L0); + } + else + { + AllocateMatrixType(2, &d.L0, 0, NumberOfRows(p->Dm)); + } + d.targetRows = NumberOfRows(p->Dm); + d.targetCols = NumberOfColumns(p->Dm); + /*Copy index lists (and fill in the corresponding flags).*/ + if (p->Tuc && p->TucCount) + { + d.Tuc = tcalloc(p->TucCount, sizeof(int)); + d.TucCount = p->TucCount; + memcpy(d.Tuc, p->Tuc, sizeof(int) * p->TucCount); + /*Make sure the index array is sorted. This will allow us to speed up + certain processing later.*/ + Sort(d.Tuc, d.TucCount); + } + if (p->Tuo && p->TuoCount) + { + d.Tuo = tcalloc(p->TuoCount, sizeof(int)); + d.TuoCount = p->TuoCount; + memcpy(d.Tuo, p->Tuo, sizeof(int) * p->TuoCount); + /*Make sure the index array is sorted. This will allow us to speed up + certain processing later.*/ + Sort(d.Tuo, d.TuoCount); + } + if (p->ExcludeT && p->ExcludeCount) + { + d.ExcludeT = tcalloc(p->ExcludeCount, sizeof(int)); + d.ExcludeCount = p->ExcludeCount; + memcpy(d.ExcludeT, p->ExcludeT, sizeof(int) * p->ExcludeCount); + /*Make sure the index array is sorted. This will allow us to speed up + certain processing later.*/ + Sort(d.ExcludeT, d.ExcludeCount); + } + if (p->IncludeT && p->IncludeCount) + { + d.IncludeT = tcalloc(p->IncludeCount, sizeof(int)); + d.IncludeCount = p->IncludeCount; + memcpy(d.IncludeT, p->IncludeT, sizeof(int) * p->IncludeCount); + /*Make sure the index array is sorted. This will allow us to speed up + certain processing later.*/ + Sort(d.IncludeT, d.IncludeCount); + } + else + { + /*If IncludeT is not present, it defaults to including all transitions.*/ + d.IncludeT = tcalloc(d.targetCols, sizeof(int)); + d.IncludeCount = d.targetCols; + for (i = 0; i < d.targetCols; i++) + { + d.IncludeT[i] = i; + } + } + /*Copy the constraint vectors*/ + if (p->B) + { + d.B = tcalloc(NumberOfRows(d.L), sizeof(int)); + memcpy(d.B, p->B, NumberOfRows(d.L) * sizeof(int)); + } + if (p->B0) + { + d.B0 = tcalloc(NumberOfRows(d.L0), sizeof(int)); + memcpy(d.B0, p->B0, NumberOfRows(d.L0) * sizeof(int)); + } + /*The only one of the state flags that does not default to zero is perm.*/ + d.state.perm = 1; + /*If the DP_OPT_ENFORCELIVE option bit is set, we are doing liveness + enforcement. If the IncludeT count is less than the total number of + transitions, we are doing T-liveness enforcement.*/ + if (p->option & DP_OPT_ENFORCELIVE) + { + if (d.targetCols > d.IncludeCount) + { + d.state.dptype = 2; + } + else + { + d.state.dptype = 1; + } + } + /*If Tuc or Tuo are present, set the uncontro state bit.*/ + if (d.Tuc || d.Tuo) + { + d.state.uncontro = 1; + } + /*If L or L0 are present, set the initial conditions (incon) state bit.*/ + if (d.L.type || d.L0.type) + { + d.state.incon = 1; + d.consis = 1; + } + /*If the DP_OPT_WRITELOG bit is set, attempt to open the log files. If either + open fails, revert to no logging and issue a warning if verbosity is turned on.*/ + if (p->option & DP_OPT_WRITELOG) + { + char *mode = (p->option & DP_OPT_APPENDLOGS) ? "a" : "w"; + char *name = (p->option & DP_OPT_APPENDLOGS) ? "append" : "write"; + if (d.log = fopen("dp.log", mode)) + { + if (! (d.dat = fopen("dp.dat", mode))) + { + if (is_verbose() >= VRB_DP) printf("Warning: Could not open file \"dp.dat\" for %s access. Logging disabled.\n", name); + fclose(d.log); + d.log = 0; + } + } + else if (is_verbose() >= VRB_DP) printf("Warning: Could not open file \"dp.log\" for %s access. Logging disabled.\n", name); + } + /*If logging is enabled go ahead and write the log headers.*/ + if (d.log) + { + char timeString[64]; + /*Matlab date format example: 24-Oct-2003 13:45:07*/ + time_t tm = time(0); + strftime(timeString, 64, "%d-%b-%Y %H:%M:%S", localtime(&tm)); + fprintf(d.log, "\n%s -- DP.log -- Generated by DP\n", timeString); + fprintf(d.dat, "\n%s -- DP.DAT -- Generated by DP\n", timeString); + fflush(d.log); + fflush(d.dat); + } + /*Set firstpass to 1 and leave restart as 0.*/ + d.firstpass = 1; + return d; +} + +/******************************************************************************* +This function checks the constraints given in L/B and L0/B0 of the dpData +structure and builds the set of complete marking constraints from them, returning +it in the MarkingConstraints structure.*/ +MarkingConstraints UpdateMarkingConstraints(dpData *d) +{ + int count; + MarkingConstraints result; + memset(&result, 0, sizeof(MarkingConstraints)); + if (NumberOfRows(d->L) || NumberOfRows(d->L0)) + { + count = NumberOfRows(d->L) + NumberOfRows(d->L0); + AllocateMatrixType(2, &result.L, count, NumberOfRows(d->Dm)); + Copy... [truncated message content] |
From: <Ste...@us...> - 2009-07-28 16:49:19
|
Revision: 209 http://pntool.svn.sourceforge.net/pntool/?rev=209&view=rev Author: StephenCamp Date: 2009-07-28 16:49:11 +0000 (Tue, 28 Jul 2009) Log Message: ----------- asiph now returns result matrices that have been set up for fast column operations. Modified Paths: -------------- spnbox/asiph.c Modified: spnbox/asiph.c =================================================================== --- spnbox/asiph.c 2009-07-28 16:38:30 UTC (rev 208) +++ spnbox/asiph.c 2009-07-28 16:49:11 UTC (rev 209) @@ -162,7 +162,8 @@ } /*The result NMS should be a transpose copy of MNS with columns not flagged in newindex removed. The result MS should be a transpose copy of MNS. Count - how many columns that is.*/ + how many columns that is. Both of the result matrices should be optimized + for column operations.*/ j = 0; for (i = 0; i < NumberOfRows(data->MNS); i++) { @@ -170,8 +171,11 @@ } asiph_r result; - AllocateMatrixType(2, &result.NMS, NumberOfColumns(data->MNS), j); - AllocateMatrixType(2, &result.MS, NumberOfColumns(data->MNS), NumberOfRows(data->MNS)); + AllocateMatrixType(2, &result.NMS, j, NumberOfColumns(data->MNS)); + AllocateMatrixType(2, &result.MS, NumberOfRows(data->MNS), NumberOfColumns(data->MNS)); + TransposeMatrix(&result.NMS); + TransposeMatrix(&result.MS); + TransposeMatrix(&data->MNS); CopyMatrix(&data->MNS, &result.MS); j = 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-28 16:38:40
|
Revision: 208 http://pntool.svn.sourceforge.net/pntool/?rev=208&view=rev Author: StephenCamp Date: 2009-07-28 16:38:30 +0000 (Tue, 28 Jul 2009) Log Message: ----------- Further optimized row & column removal - now it skips allocating even a new ar member if possible. Added OptimizeColumns and OptimizeRows, functions that set a given matrix up for speed-optimized column or row operations. Modified the test routine as appropriate. Modified Paths: -------------- spnbox/extendedmatrix.c spnbox/extendedmatrix.h spnbox/tests/test-extendedmatrix.c spnbox/tests/test-extendedmatrix.txt Modified: spnbox/extendedmatrix.c =================================================================== --- spnbox/extendedmatrix.c 2009-07-27 01:47:57 UTC (rev 207) +++ spnbox/extendedmatrix.c 2009-07-28 16:38:30 UTC (rev 208) @@ -217,15 +217,19 @@ { matrix result; - /*Prepare the result matrix.*/ + /*Allocate the result matrix. Preserve transpose state.*/ + int nr = m->trans ? NumberOfColumns(*m) : NumberOfRows(*m) - rows; + int nc = m->trans ? NumberOfRows(*m) - rows : NumberOfColumns(*m); if (mode) { - AllocateMatrixType(mode, &result, NumberOfRows(*m) - rows, NumberOfColumns(*m)); + AllocateMatrixType(mode, &result, nr, nc); } else { - AllocateMatrix(&result, NumberOfRows(*m) - rows, NumberOfColumns(*m)); + AllocateMatrix(&result, nr, nc); } + if (m->trans) TransposeMatrix(&result); + /*Copy the first-half block.*/ if (row) { @@ -240,30 +244,21 @@ } matrix RemoveRowsOrig(matrix* m, int row, int rows) -{ - mtype** newAr; +{ int i; /*Check to see if the remove can be optimized.*/ if (m->type == 2 && (! m->trans)) { - newAr = tcalloc(m->nr, sizeof(mtype*)); - for (i = 0; i < m->nr; i++) + /*Do not allocate a new ar member if we can help it. Just leave the old one + and move the memory.*/ + for (i = row; i < row + rows; i++) { - if (i < row) - { - newAr[i] = m->ar[i]; - } - else if (i < row + rows) - { - free(m->ar[i]); - } - else - { - newAr[i - rows] = m->ar[i]; - } + free(m->ar[i]); } - free(m->ar); - m->ar = newAr; + for (i = row + rows; i < m->nr; i++) + { + m->ar[i - rows] = m->ar[i]; + } m->nr -= rows; } else @@ -280,15 +275,19 @@ matrix InsertNullRowsCopy(matrix *m, int row, int rows, int mode) { matrix result; - /*Allocate the result matrix.*/ + /*Allocate the result matrix. Preserve transpose state.*/ + int nr = m->trans ? NumberOfColumns(*m) : NumberOfRows(*m) + rows; + int nc = m->trans ? NumberOfRows(*m) + rows : NumberOfColumns(*m); if (mode) { - AllocateMatrixType(mode, &result, NumberOfRows(*m) + rows, NumberOfColumns(*m)); + AllocateMatrixType(mode, &result, nr, nc); } else { - AllocateMatrix(&result, NumberOfRows(*m) + rows, NumberOfColumns(*m)); + AllocateMatrix(&result, nr, nc); } + if (m->trans) TransposeMatrix(&result); + /*Copy the first-half block.*/ if (row) { @@ -339,3 +338,22 @@ } return *m; } + +void OptimizeRows(matrix* m) +{ + matrix newM; + if (m->type != 2 || m->trans) + { + AllocateMatrixType(2, &newM, NumberOfRows(*m), NumberOfColumns(*m)); + CopyMatrix(m, &newM); + DeallocateMatrix(m); + *m = newM; + } +} + +void OptimizeColumns(matrix *m) +{ + TransposeMatrix(m); + OptimizeRows(m); + TransposeMatrix(m); +} Modified: spnbox/extendedmatrix.h =================================================================== --- spnbox/extendedmatrix.h 2009-07-27 01:47:57 UTC (rev 207) +++ spnbox/extendedmatrix.h 2009-07-28 16:38:30 UTC (rev 208) @@ -83,4 +83,12 @@ RemoveColumns is able to employ the same type of optimization as RemoveRows (reducing computational complexity by a factor at least equal to the number of rows in the matrix) if and only if the matrix is a type-2 transposed.*/ + +void OptimizeRows(matrix *m); +/*OptimizeRows modifies the matrix passed to it so that its use with the row- +manipulation functions will be optimized for speed.*/ + +void OptimizeColumns(matrix *m); +/*OptimizeColumns modifies the matrix passed to it so that its use with the +column-manipulation functions will be optimized for speed.*/ #endif Modified: spnbox/tests/test-extendedmatrix.c =================================================================== --- spnbox/tests/test-extendedmatrix.c 2009-07-27 01:47:57 UTC (rev 207) +++ spnbox/tests/test-extendedmatrix.c 2009-07-28 16:38:30 UTC (rev 208) @@ -27,6 +27,8 @@ static void SInsertNullC(int Size, int Reps, int Col, int Cols, int Optimized); static void TInsertNullR(matrix *A, int Row, int Rows, int Mode, int Optimized); static void TInsertNullC(matrix *A, int Col, int Cols, int Mode, int Optimized); +static void TOptimizeR(matrix *A); +static void TOptimizeC(matrix *A); static void PrintPercent(int num, int denom); static matrix* AllocateMatrices(int rows, int cols, int Reps, int Transpose); @@ -125,6 +127,14 @@ TRemoveC(&A, Column, Columns, Mode, Optimized); } } + else if (! strcmp(Operation, "OptimizeRows")) + { + TOptimizeR(&A); + } + else if (! strcmp(Operation, "OptimizeColumns")) + { + TOptimizeC(&A); + } else { printf("Warning: Unrecognized operation '%s'.\n", Operation); @@ -428,6 +438,22 @@ if (Mode >= 0) DeallocateMatrix(&result); } +void TOptimizeR(matrix *A) +{ + ShowMatrix(A, "A before row optimization"); + OptimizeRows(A); + ShowMatrix(A, "A after row optimization"); + printf("A is %stransposed", A->trans ? "" : "un"); +} + +void TOptimizeC(matrix *A) +{ + ShowMatrix(A, "A before column optimization"); + OptimizeColumns(A); + ShowMatrix(A, "A after column optimization"); + printf("A is %stransposed.\n", A->trans ? "" : "un"); +} + /*Display a progress percentage that changes with time instead of being left in the output buffer.*/ void PrintPercent(int num, int denom) @@ -490,4 +516,4 @@ *Reps = 1; *Size = 2; strcpy(speedtest, "no"); -} \ No newline at end of file +} Modified: spnbox/tests/test-extendedmatrix.txt =================================================================== --- spnbox/tests/test-extendedmatrix.txt 2009-07-27 01:47:57 UTC (rev 207) +++ spnbox/tests/test-extendedmatrix.txt 2009-07-28 16:38:30 UTC (rev 208) @@ -3,7 +3,8 @@ rem speedtest: string = "yes", "no". Sets whether a speedtest should be done. rem Defaults to "no". rem operation. string = InsertRows, InsertColumns, InsertNullRows, -rem InsertNullColumns, RemoveRows, RemoveColumns. Selects the operation to test. +rem InsertNullColumns, RemoveRows, RemoveColumns, OptimizeRows, OptimizeColumns. +rem Selects the operation to test. rem mode: integer. Sets the mode of the operation (>=0 performs a copy-type rem operation and <0 performs an operation on the original matrix.) Defaults to rem 0. @@ -197,4 +198,21 @@ row 1 rows 2 done + +echo Problem 19. Row optimization. +A 3 5 +1 2 3 4 5 +5 4 3 2 1 +1 2 3 4 5 +operation OptimizeRows +done + +echo Problem 20. Column optimization. +A 3 5 +1 2 3 4 5 +5 4 3 2 1 +1 2 3 4 5 +operation OptimizeColumns +done + quit This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-27 01:48:07
|
Revision: 207 http://pntool.svn.sourceforge.net/pntool/?rev=207&view=rev Author: StephenCamp Date: 2009-07-27 01:47:57 +0000 (Mon, 27 Jul 2009) Log Message: ----------- Actually adding fvpr.c and the test files this time... Added Paths: ----------- spnbox/fvpr.c spnbox/tests/test-fvpr.c spnbox/tests/test-fvpr.txt Added: spnbox/fvpr.c =================================================================== --- spnbox/fvpr.c (rev 0) +++ spnbox/fvpr.c 2009-07-27 01:47:57 UTC (rev 207) @@ -0,0 +1,148 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "../pnheaders/general.h" +#include "../pnheaders/matrix.h" +#include "spnbox.h" + +static char* buffer = 0; +static int bufferLength = 0; + +static int GetBufferLength(void* vector, int length, int mode, char* op, char* cl); +static int GetVectorEl(void* vector, int i, int mode); +static int CheckParams(void* vector, int length, int mode, int option); + +char* fvpr(void* vector, int length, int mode, int option) +{ + char *op, *cl; + char element[64]; + + /*If the vector is a matrix, get the length.*/ + if (mode == DISPLAY_MATRIX) length = MatrixLength(*((matrix*)vector)); + + /*Check the parameters.*/ + if (! CheckParams(vector, length, mode, option)) return 0; + + /*Get the characters that will (maybe) be printed to begin and end the + vector.*/ + switch(option) + { + case 0: + op = ""; + cl = ""; + break; + case 1: + if (length > 1) + { + op = "["; + cl = "]"; + } + else + { + op = ""; + cl = ""; + } + break; + case 2: + op = "{"; + cl = "}"; + break; + } + + /*Get the length of buffer that will be needed. Do not reallocate space unless + we need to.*/ + int i, newBufferLength = GetBufferLength(vector, length, mode, op, cl); + if (newBufferLength > bufferLength) + { + free(buffer); + bufferLength = newBufferLength; + buffer = calloc(bufferLength, sizeof(char)); + } + buffer[0] = '\0'; + if (! length) return buffer; + + /*Do the printing.*/ + strcpy(buffer, op); + for (i = 0; i < length; i++) + { + int c = GetVectorEl(vector, i, mode); + sprintf(element, i ? ", %d" : "%d", c); + strcat(buffer, element); + } + strcat(buffer, cl); + if (mode == DISPLAY_MATRIX && NumberOfRows(*((matrix*)vector)) > 1) + { + strcat(buffer, "'"); + } + return buffer; +} + +int GetBufferLength(void* vector, int length, int mode, char* op, char* cl) +{ + if (length == 0) return 1; + /*The buffer length will be, at most, the vector length times the length of + the element separator plus the number of digits required to display the + largest number in the vector, all plus the lengths of the beginning and ending + separators.*/ + /*To get the number of digits, find the maximum and then do a simple logarithm.*/ + int max = 1, digits = 1, i; + for (i = 0; i < length; i++) + { + int c = GetVectorEl(vector, i, mode); + if (c > max) max = c; + if (-c > max) max = -c; + } + /*Perform a simple logarithm. The number of digits begins at 1, not zero, + because we are leaving space for a minus sign.*/ + + while(max) + { + max /= 10; + digits++; + } + + return strlen(op) + strlen(cl) + ((strlen(", ") + digits) * length) + 1 + (mode == DISPLAY_MATRIX) ? 1 : 0; +} + +int GetVectorEl(void* vector, int i, int mode) +{ + switch(mode) + { + case DISPLAY_MATRIX: + return GetMatrixEl((matrix*) vector, i % NumberOfRows(* ((matrix*) vector)), i / NumberOfRows(* ((matrix*) vector))); + break; + case DISPLAY_INTS: + return ((int*)vector)[i]; + break; + } +} + +int CheckParams(void* vector, int length, int mode, int option) +{ + /*vector and destination are both required.*/ + if (! vector) + { + merror(0, "FVPR: A required pointer was null"); + return 0; + } + /*length cannot be non-positive.*/ + if (length < 1) + { + merror(0, "FVPR: Vector length is non-positive"); + return 0; + } + /*If the chr is 0, fill it with the default, m.*/ + if (mode != DISPLAY_MATRIX && mode !=DISPLAY_INTS) + { + merror(0, "FVPR: Invalid mode"); + return 0; + } + if (option < 0 || option > 2) + { + merror(0, "FVPR: Invalid option"); + return 0; + } + return 1; +} + + \ No newline at end of file Added: spnbox/tests/test-fvpr.c =================================================================== --- spnbox/tests/test-fvpr.c (rev 0) +++ spnbox/tests/test-fvpr.c 2009-07-27 01:47:57 UTC (rev 207) @@ -0,0 +1,52 @@ +#include "test.h" + +int main(int argc, char* argv[]) +{ + char iDesc[] = "arrayi V, matrix M, int option"; + char *result; + int* vector = 0; + int vLength = 0; + int option = 1; + int *iFill; + matrix M; + + FILE* file; + + if (! (file = ParseCmdLine(argc, argv))) + { + return 0; + } + + MemoryManager mem = CreateMemoryManager(3, 1, 0, 0); + + while (ParseStructure(file, iDesc, &iFill, &mem, &vector, &vLength, &M, &option)) + { + if (iFill[0]) iFill[1] = 0; + DisplayStructure(iDesc, iFill, vector, vLength, &M, option); + + if (iFill[0]) + { + result = fvpr(vector, vLength, DISPLAY_INTS, option); + } + else if (iFill[1]) + { + result = fvpr(&M, 0, DISPLAY_MATRIX, option); + } + else + { + result = " No vector or matrix provided!"; + } + + printf("Result:\n%s\n", result); + + FreeMemory(&mem); + mem = CreateMemoryManager(3, 0, 0, 0); + + vector = 0; + vLength = 0; + option = 1; + + printf("-------------------------------------------------------------------------------\n"); + } + return 0; +} Added: spnbox/tests/test-fvpr.txt =================================================================== --- spnbox/tests/test-fvpr.txt (rev 0) +++ spnbox/tests/test-fvpr.txt 2009-07-27 01:47:57 UTC (rev 207) @@ -0,0 +1,35 @@ +echo Problem 1. +echo Solution should be: +echo [-100, -100, -100] +V 3 +-100 -100 -100 +done + +echo Problem 2. +echo Solution should be: +echo 1 +V 1 1 +done + +echo Problem 3. +echo Solution should be: +echo 1 +M 1 1 1 +done + +echo Problem 4. +echo Solution should be: +echo [1, 4, 2, 5, 3, 6]' +M 2 3 +1 2 3 +4 5 6 +done + +echo Problem 5. +echo Solution should be: +echo {1, 2, 3, 4, 5, 6} +M 1 6 +1 2 3 4 5 6 +option 2 +done +quit \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-25 00:47:02
|
Revision: 206 http://pntool.svn.sourceforge.net/pntool/?rev=206&view=rev Author: StephenCamp Date: 2009-07-25 00:46:51 +0000 (Sat, 25 Jul 2009) Log Message: ----------- Added fvpr.c, test routines, and makefile entries. Modified avpr.c. fvpr and avpr now can accept either matrices or integer arrays for the vectors. Modified Paths: -------------- spnbox/avpr.c spnbox/spnbox.h spnbox/tests/Makefile spnbox/tests/test-avpr.c spnbox/tests/test-avpr.txt Modified: spnbox/avpr.c =================================================================== --- spnbox/avpr.c 2009-07-24 19:54:56 UTC (rev 205) +++ spnbox/avpr.c 2009-07-25 00:46:51 UTC (rev 206) @@ -1,77 +1,163 @@ #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include "../pnheaders/general.h" +#include "../pnheaders/matrix.h" +#include "spnbox.h" -static int CheckParams(double* vector, int length, char** chr, char* destination); +/*The answer that avpr returns is a pointer to this buffer. It is reset with each +call to avpr.*/ +static char* buffer = 0; +static int bufferLength = 0; -void avpr(double *vector, int length, char* chr, int option, char* destination) +static int CheckParams(int* vector, int length, int mode, char** chr); +static int GetVectorEl(void* vector, int i, int mode); +static int GetBufferLength(void* vector, int length, int mode, char* chr, char* bl, char* el); + +char* avpr(void *vector, int length, int mode, char* chr, int option) { char element[64]; + if (mode == DISPLAY_MATRIX) length = MatrixLength(*((matrix*) vector)); + /*Fill in default parameters.*/ - if (! CheckParams(vector, length, &chr, destination)) - { - return; - } + if (! CheckParams(vector, length, mode, &chr)) return 0; + + /*If the vector is a matrix, get the length from it.*/ + /*Setup bl and el - some kind of beginning and terminating strings.*/ char *bl = option ? "_{" : ""; char *el = option ? "}" : ""; - /*Destination defaults to an empty string.*/ - destination[0] = '\0'; + /*Setup the destination buffer. Begin by determining the maximum length we + will need. It is, at most, the number of nonzero entries in the vector times + the sum of the lengths of the various string parts times the base-10 log of + the length of the vector.*/ + int i, newBufferLength = GetBufferLength(vector, length, mode, chr, bl, el); - /*Iterate through the elements in the vector, processing only nonzero - elements. The first nonzero element is processed differently than the others, - so use a flag to indicate whether the first nonzero element has been found or - not.*/ - int firstProcessed = 0; - int i; + //Allocate new space only if necessary. + if (newBufferLength > bufferLength) + { + free(buffer); + bufferLength = newBufferLength; + buffer = tcalloc(bufferLength, sizeof(char)); + } + //The buffer defaults to an empty string. + buffer[0] = '\0'; + /*If there are no nonzero entries, newBufferLength will be 1 and we should + return an empty string.*/ + if (newBufferLength == 1) + { + return buffer; + } + + int firstProcessed = 0; for (i = 0; i < length; i++) { - if (! vector[i]) continue; + int c = GetVectorEl(vector, i, mode); + if (! c) continue; if (! firstProcessed) { - if (vector[i] == 1) + if (c == 1) { sprintf(element, "%s%s%d%s", chr, bl, i + 1, el); } - else if (vector[i] == -1) + else if (c == -1) { sprintf(element, "-%s%s%d%s", chr, bl, i + 1, el); } else { - sprintf(element, "%g%s%s%d%s", vector[i], chr, bl, i + 1, el); + sprintf(element, "%d%s%s%d%s", c, chr, bl, i + 1, el); } firstProcessed = 1; } else { - if (vector[i] == 1) + if (c == 1) { sprintf(element, "+%s%s%d%s", chr, bl, i + 1, el); } - else if (vector[i] > 0) + else if (c > 0) { - sprintf(element, "+%g%s%s%d%s", vector[i], chr, bl, i + 1, el); + sprintf(element, "+%d%s%s%d%s", c, chr, bl, i + 1, el); } - else if (vector[i] == -1) + else if (c == -1) { sprintf(element, "-%s%s%d%s", chr, bl, i + 1, el); } else { - sprintf(element, "%g%s%s%d%s", vector[i], chr, bl, i + 1, el); + sprintf(element, "%d%s%s%d%s", c, chr, bl, i + 1, el); } } - strcat(destination, element); + strcat(buffer, element); } + return buffer; } -int CheckParams(double* vector, int length, char** chr, char* destination) +int GetBufferLength(void* vector, int length, int mode, char* chr, char* bl, char* el) { + /*The largest the new buffer will be will be related to the length required + for each nonzero element. Each element's length will max out at: the number of + digits required to display the largest element in the vector plus the number + of digits required to display the largest nonzero index in the vector plus the + number of characters required to display the strings chr, bl, and el.*/ + int indexMax = 0, elementMax = 0; + int indexDigits = 0, elementDigits = 1, i; + int result = 0; + for (i = 0; i < length; i++) + { + int c = GetVectorEl(vector, i, mode); + if (c) + { + indexMax = i; + result++; + if (c > elementMax) elementMax = c; + if (c < -elementMax) elementMax = -c; + } + } + /*If there were no nonzero vectors, the buffer length just needs to be 1.*/ + if (! result) return 1; + /*To find the number of digits required to display the maximum, do an + approximate base-10 logarithm.*/ + elementMax++; + while (elementMax) + { + elementMax /= 10; + elementDigits++; + } + indexMax++; + while (indexMax) + { + indexMax /= 10; + indexDigits++; + } + /*Now, assume each nonzero element displays chr, bl, el, an index, and the + element value:*/ + result *= (strlen(chr) + strlen(bl) + strlen(el) + indexDigits + elementDigits); + /*Add 1 for the null terminator and return.*/ + return ++result; +} + +int GetVectorEl(void* vector, int i, int mode) +{ + switch(mode) + { + case DISPLAY_MATRIX: + return GetMatrixEl((matrix*) vector, i % NumberOfRows(* ((matrix*) vector)), i / NumberOfRows(* ((matrix*) vector))); + break; + case DISPLAY_INTS: + return ((int*)vector)[i]; + break; + } +} + +int CheckParams(int* vector, int length, int mode, char** chr) +{ /*vector and destination are both required.*/ - if (! (vector && destination)) + if (! vector) { merror(0, "AVPR: A required pointer was null"); return 0; @@ -87,5 +173,11 @@ { *chr = "m"; } + if (mode != DISPLAY_MATRIX && mode !=DISPLAY_INTS) + { + merror(0, "AVPR: Invalid mode"); + return 0; + } return 1; -} \ No newline at end of file +} + \ No newline at end of file Modified: spnbox/spnbox.h =================================================================== --- spnbox/spnbox.h 2009-07-24 19:54:56 UTC (rev 205) +++ spnbox/spnbox.h 2009-07-25 00:46:51 UTC (rev 206) @@ -229,6 +229,10 @@ #define VRB_ASIPH 3 #define VRB_MAX 10 +/*Constaints used to change the behavior of the vector dispaly functions.*/ +#define DISPLAY_MATRIX 0 +#define DISPLAY_INTS 1 + msplit_r msplit(matrix* Dm, matrix* Dp, int* mask, matrix* M, matrix* L0, matrix* L, int* ipl, int ipCount, int* dpl, int dpCount, int** TD, int* TDCount); /*MSPLIT - split transitions to make a Petri net PT-ordinary. Original Matlab Usage: @@ -932,7 +936,7 @@ size must be appropriate (same number of rows as there are dependent places, same number of columns as there are independent places).*/ -void avpr(double *vector, int length, char* chr, int option, char* destination); +char* avpr(void *vector, int length, int mode, char* chr, int option); /* AVPR - Transforms a vector in a string to be used for displaying equations/inequalities. @@ -951,9 +955,30 @@ Written for Matlab by Marian V. Iordache, mar...@le.... Converted to C by Marian V. Iordache and Stephen Camp, ste...@le.... -C Usage: Parameters have the same meaning and names as in Matlab, with the -addition of the destination parameter, a pointer to a character array that will -be filled with the result. The array is not checked to make sure it has enough -space; this is left to the caller. -If chr is a null pointer it will default to m, as in Matlab.*/ +C Usage: Parameters have the same meaning and names as in Matlab. +If chr is a null pointer it will default to m, as in Matlab. +Use mode = DISPLAY_MATRIX for vector a pointer to a matrix. length is ignored. +Use mode = DISPLAY_INTS for vector a pointer to an array of integers. +The function returns a pointer to a static buffer that it owns. This buffer is +overwritten every time the function is called. The caller should use or copy the +buffer immediately after calling the function.*/ + +char* fvpr(void* vector, int length, int mode, int option); +/*FVPR - Transforms a vector in a string + +[str] = fvpr(x) + +Use the format below to print finite sets + +[str] = fvpr(x,2) + +Written for Matlab by Marian V. Iordache, mar...@le.... +Converted to C by Marian V. Iordache and Stephen Camp, ste...@le.... +C Usage: Parameters have the same meaning and names as in Matlab. +Use mode = DISPLAY_MATRIX for vector a pointer to a matrix. length is ignored. +Use mode = DISPLAY_INTS for vector a pointer to an array of integers. +The function returns a pointer to a static buffer that it owns. This buffer is +overwritten every time the function is called. The caller should use or copy the +buffer immediately after calling the function.*/ + #endif Modified: spnbox/tests/Makefile =================================================================== --- spnbox/tests/Makefile 2009-07-24 19:54:56 UTC (rev 205) +++ spnbox/tests/Makefile 2009-07-25 00:46:51 UTC (rev 206) @@ -12,6 +12,7 @@ #These symbols define the dependencies of various test executables. AVPR=avpr.o EXTENDEDMATRIX=extendedmatrix.o +FVPR=fvpr.o IPSLV=ipslv.o ../liblpsolve55.a IPSOLVE=ipsolve.o $(IPSLV) ISADM=isadm.o @@ -38,6 +39,8 @@ $(COMPILER) -o avpr.exe test-avpr.o $(AVPR) $(COMMON) extendedmatrix: test-extendedmatrix.o $(EXTENDEDMATRIX) $(COMMON) $(COMPILER) -o extendedmatrix.exe test-extendedmatrix.o $(EXTENDEDMATRIX) $(COMMON) +fvpr: test-fvpr.o $(FVPR) $(COMMON) + $(COMPILER) -o fvpr.exe test-fvpr.o $(FVPR) $(COMMON) ipslv: test-ipslv.o $(IPSLV) $(COMPILER) -o ipslv.exe test-ipslv.o $(IPSLV) ipsolve: test-ipsolve.o $(COMMON) $(IPSOLVE) @@ -90,6 +93,8 @@ $(COMPILER) -c ../deallocation.c extendedmatrix.o: ../extendedmatrix.c ../extendedmatrix.h ../../pnheaders/matrix.h ../../pnheaders/general.h $(COMPILER) -c ../extendedmatrix.c +fvpr.o: ../fvpr.c + $(COMPILER) -c ../fvpr.c general.o: ../../pnheaders/general.c ../../pnheaders/general.h $(COMPILER) -c ../../pnheaders/general.c ilpadm.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../ilpadm.c @@ -142,6 +147,8 @@ $(COMPILER) -c test-avpr.c test-extendedmatrix.o: test-extendedmatrix.c $(COMMONHEADER) $(COMPILER) -c test-extendedmatrix.c +test-fvpr.o: test-fvpr.c $(COMMONHEADER) + $(COMPILER) -c test-fvpr.c test-ilpadm.o: test-ilpadm.c $(COMMONHEADER) $(COMPILER) -c test-ilpadm.c test-ipslv.o: test-ipslv.c Modified: spnbox/tests/test-avpr.c =================================================================== --- spnbox/tests/test-avpr.c 2009-07-24 19:54:56 UTC (rev 205) +++ spnbox/tests/test-avpr.c 2009-07-25 00:46:51 UTC (rev 206) @@ -2,12 +2,13 @@ int main(int argc, char* argv[]) { - char iDesc[] = "arrayd vector, string chr, int option, int maxlength"; - double* vector = 0; - int vLength = 0, option = 0, maxlength = 256; - char *destination; + char iDesc[] = "arrayi V, matrix M, string chr, int option"; + char *result; + int* vector = 0; + int vLength = 0, option = 0; char chr[128] = ""; int *iFill; + matrix M; FILE* file; @@ -16,26 +17,34 @@ return 0; } - MemoryManager mem = CreateMemoryManager(3, 0, 0, 0); + MemoryManager mem = CreateMemoryManager(3, 1, 0, 0); - while (ParseStructure(file, iDesc, &iFill, &mem, &vector, &vLength, chr, &option, &maxlength)) + while (ParseStructure(file, iDesc, &iFill, &mem, &vector, &vLength, &M, chr, &option)) { - DisplayStructure(iDesc, iFill, vector, vLength, chr, option, maxlength); + if (iFill[0]) iFill[1] = 0; + DisplayStructure(iDesc, iFill, vector, vLength, &M, chr, option); - if (maxlength < 2 || maxlength > 5000) maxlength = 256; - destination = mcalloc(&mem, maxlength, sizeof(char)); + if (iFill[0]) + { + result = avpr(vector, vLength, DISPLAY_INTS, chr, option); + } + else if (iFill[1]) + { + result = avpr(&M, 0, DISPLAY_MATRIX, chr, option); + } + else + { + result = " No vector or matrix provided!"; + } - avpr(vector, vLength, chr, option, destination); + printf("Result:\n%s\n", result); - printf("Result:\n%s\n", destination); - FreeMemory(&mem); mem = CreateMemoryManager(3, 0, 0, 0); vector = 0; vLength = 0; option = 0; - maxlength = 256; chr[0] = '\0'; printf("-------------------------------------------------------------------------------\n"); } Modified: spnbox/tests/test-avpr.txt =================================================================== --- spnbox/tests/test-avpr.txt 2009-07-24 19:54:56 UTC (rev 205) +++ spnbox/tests/test-avpr.txt 2009-07-25 00:46:51 UTC (rev 206) @@ -1,59 +1,69 @@ echo Problem 1. echo Solution should be: echo <empty string> -vector 1 +V 1 0 done echo Problem 2. echo Solution should be: echo m1 -vector 1 +V 1 1 done echo Problem 3. echo Solution should be: echo -m1 -vector 1 +V 1 -1 done echo Problem 4. echo Solution should be: echo 2m1 -vector 1 +V 1 2 done echo Problem 5 echo Solution should be: echo -2m1 -vector 1 +V 1 -2 done echo Problem 6 echo Solution should be: echo -2m1-m2+m4+2m5 -vector 5 +V 5 -2 -1 0 1 2 done echo Problem 7 echo Solution should be: -echo -2.5z1-z2+z4+2.5z5 -vector 5 --2.5 -1 0 1 2.5 +echo -2z1-z2+z4+2z5 +V 5 +-2 -1 0 1 2 chr z done echo Problem 8 echo Solution should be: -echo -2.5m_{1}-m_{2}+m_{4}+2.5m_{5} -vector 5 --2.5 -1 0 1 2.5 +echo -2m_{1}-m_{2}+m_{4}+2m_{5} +V 5 +-2 -1 0 1 2 option 1 done + +echo Problem 9 +echo Solution should be: +echo -2m_{1}-m_{2}+m_{4}+2m_{5} +M 3 2 +-2 1 +-1 2 + 0 0 +option 1 +done quit This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-24 19:55:03
|
Revision: 205 http://pntool.svn.sourceforge.net/pntool/?rev=205&view=rev Author: StephenCamp Date: 2009-07-24 19:54:56 +0000 (Fri, 24 Jul 2009) Log Message: ----------- Corrected a bug (memory leak) in chkcons.c. Modified Paths: -------------- spnbox/chkcons.c Modified: spnbox/chkcons.c =================================================================== --- spnbox/chkcons.c 2009-07-24 19:33:30 UTC (rev 204) +++ spnbox/chkcons.c 2009-07-24 19:54:56 UTC (rev 205) @@ -45,7 +45,7 @@ empty.*/ else { - free(result.res); + if (IPSolution.res) free(IPSolution.res); } /*Free intermediate memory and return.*/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-24 19:33:38
|
Revision: 204 http://pntool.svn.sourceforge.net/pntool/?rev=204&view=rev Author: StephenCamp Date: 2009-07-24 19:33:30 +0000 (Fri, 24 Jul 2009) Log Message: ----------- Changed the avpr test script so that it now lists what the results of each test should be correctly. Modified Paths: -------------- spnbox/tests/test-avpr.txt Modified: spnbox/tests/test-avpr.txt =================================================================== --- spnbox/tests/test-avpr.txt 2009-07-24 19:30:11 UTC (rev 203) +++ spnbox/tests/test-avpr.txt 2009-07-24 19:33:30 UTC (rev 204) @@ -7,42 +7,42 @@ echo Problem 2. echo Solution should be: -echo m0 +echo m1 vector 1 1 done echo Problem 3. echo Solution should be: -echo -m0 +echo -m1 vector 1 -1 done echo Problem 4. echo Solution should be: -echo 2m0 +echo 2m1 vector 1 2 done echo Problem 5 echo Solution should be: -echo -2m0 +echo -2m1 vector 1 -2 done echo Problem 6 echo Solution should be: -echo -2m0-m1+m3+2m4 +echo -2m1-m2+m4+2m5 vector 5 -2 -1 0 1 2 done echo Problem 7 echo Solution should be: -echo -2.5z0-z1+z3+2.5z4 +echo -2.5z1-z2+z4+2.5z5 vector 5 -2.5 -1 0 1 2.5 chr z @@ -50,7 +50,7 @@ echo Problem 8 echo Solution should be: -echo -2.5m_{0}-m_{1}+m_{3}+2.5m_{4} +echo -2.5m_{1}-m_{2}+m_{4}+2.5m_{5} vector 5 -2.5 -1 0 1 2.5 option 1 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-24 19:30:25
|
Revision: 203 http://pntool.svn.sourceforge.net/pntool/?rev=203&view=rev Author: StephenCamp Date: 2009-07-24 19:30:11 +0000 (Fri, 24 Jul 2009) Log Message: ----------- Changed avpr.c to print indices that start at 1 instead of 0. Corrected admcon.c; matrix DX was being built as the transpose of what it was supposed to be. Modified Paths: -------------- spnbox/admcon.c spnbox/avpr.c Modified: spnbox/admcon.c =================================================================== --- spnbox/admcon.c 2009-07-24 03:38:40 UTC (rev 202) +++ spnbox/admcon.c 2009-07-24 19:30:11 UTC (rev 203) @@ -311,8 +311,8 @@ again.*/ matrix BuildDX(admcon_p *p, admcon_r *result, matrix *Z) { - /*DX is a matrix composed of a right-to-left concatentation of submatrices: - DX = [Auc, Auo, -Auo, -Ds, d] + /*DX is a matrix composed of a right-to-left concatentation of submatrices, all transposed: + DX = [Auc, Auo, -Auo, -Ds, d]' For: Auc = Z * DI(:,Tuc) Auo = Z * DI(:,Tuo) @@ -322,7 +322,7 @@ */ /*Allocate DX.*/ matrix DX; - AllocateMatrixType(2, &DX, NumberOfRows(*Z), p->TucCount + p->TuoCount + p->TuoCount + p->ntCount + 1); + AllocateMatrixType(2, &DX, p->TucCount + p->TuoCount + p->TuoCount + p->ntCount + 1, NumberOfRows(*Z)); int i, j, k; for (i = 0; i < NumberOfRows(DX); i++) @@ -330,26 +330,26 @@ /*Fill in Auc.*/ for (j = 0; j < p->TucCount; j++) { - SetMatrixEl(&DX, i, j, MultiplyVector(Z, &p->DI, i, p->Tuc[j], 0)); + SetMatrixEl(&DX, j, i, MultiplyVector(Z, &p->DI, i, p->Tuc[j], 0)); } /*Fill in Auo and -Auo.*/ for (j = 0; j < p->TuoCount; j++) { k = MultiplyVector(Z, &p->DI, i, p->Tuo[j], 0); - SetMatrixEl(&DX, i, j + p->TucCount, k); - SetMatrixEl(&DX, i, j + p->TucCount + p->TuoCount, -k); + SetMatrixEl(&DX, j + p->TucCount, i, k); + SetMatrixEl(&DX, j + p->TucCount + p->TuoCount, i, -k); } /*Fill in -Ds.*/ for (j = 0; j < p->ntCount; j++) { k = GetMatrixEl(&p->Dm, i, p->ntr[j]) - GetMatrixEl(&p->Dp, i, p->ntr[j]); - SetMatrixEl(&DX, i, j + p->TucCount + (2 * p->TuoCount), k); - } + SetMatrixEl(&DX, j + p->TucCount + (2 * p->TuoCount), i, k); + } } /*Fill in d.*/ for (i = 0; i < p->apCount; p++) { - SetMatrixEl(&DX, p->apl[i], NumberOfColumns(DX) - 1, 1); + SetMatrixEl(&DX, NumberOfRows(DX) - 1, p->apl[i], 1); } /*Deallocate Z. It will not be needed anymore.*/ DeallocateMatrix(Z); Modified: spnbox/avpr.c =================================================================== --- spnbox/avpr.c 2009-07-24 03:38:40 UTC (rev 202) +++ spnbox/avpr.c 2009-07-24 19:30:11 UTC (rev 203) @@ -33,15 +33,15 @@ { if (vector[i] == 1) { - sprintf(element, "%s%s%d%s", chr, bl, i, el); + sprintf(element, "%s%s%d%s", chr, bl, i + 1, el); } else if (vector[i] == -1) { - sprintf(element, "-%s%s%d%s", chr, bl, i, el); + sprintf(element, "-%s%s%d%s", chr, bl, i + 1, el); } else { - sprintf(element, "%g%s%s%d%s", vector[i], chr, bl, i, el); + sprintf(element, "%g%s%s%d%s", vector[i], chr, bl, i + 1, el); } firstProcessed = 1; } @@ -49,19 +49,19 @@ { if (vector[i] == 1) { - sprintf(element, "+%s%s%d%s", chr, bl, i, el); + sprintf(element, "+%s%s%d%s", chr, bl, i + 1, el); } else if (vector[i] > 0) { - sprintf(element, "+%g%s%s%d%s", vector[i], chr, bl, i, el); + sprintf(element, "+%g%s%s%d%s", vector[i], chr, bl, i + 1, el); } else if (vector[i] == -1) { - sprintf(element, "-%s%s%d%s", chr, bl, i, el); + sprintf(element, "-%s%s%d%s", chr, bl, i + 1, el); } else { - sprintf(element, "%g%s%s%d%s", vector[i], chr, bl, i, el); + sprintf(element, "%g%s%s%d%s", vector[i], chr, bl, i + 1, el); } } strcat(destination, element); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-24 03:38:48
|
Revision: 202 http://pntool.svn.sourceforge.net/pntool/?rev=202&view=rev Author: StephenCamp Date: 2009-07-24 03:38:40 +0000 (Fri, 24 Jul 2009) Log Message: ----------- avpr & test routines added. avpr passes tests. Makefiles modified as appropriate. Modified Paths: -------------- spnbox/Makefile spnbox/spnbox.h spnbox/tests/Makefile Added Paths: ----------- spnbox/avpr.c spnbox/tests/test-avpr.c spnbox/tests/test-avpr.txt Modified: spnbox/Makefile =================================================================== --- spnbox/Makefile 2009-07-23 21:37:10 UTC (rev 201) +++ spnbox/Makefile 2009-07-24 03:38:40 UTC (rev 202) @@ -3,7 +3,7 @@ COMPILER=gcc -g -all: actn.o admcon.o asiph.o chkcons.o deallocation.o extendedmatrix.o ilpadm.o ipslv.o ipsolve.o isadm.o issiph.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a +all: actn.o admcon.o asiph.o avpr.o chkcons.o deallocation.o extendedmatrix.o ilpadm.o ipslv.o ipsolve.o isadm.o issiph.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a actn.o: actn.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c actn.c @@ -14,6 +14,9 @@ asiph.o: asiph.c spnbox.h extendedmatrix.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c asiph.c +avpr.o: avpr.c + $(COMPILER) -c avpr.c + chkcons.o: chkcons.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h $(COMPILER) -c chkcons.c Added: spnbox/avpr.c =================================================================== --- spnbox/avpr.c (rev 0) +++ spnbox/avpr.c 2009-07-24 03:38:40 UTC (rev 202) @@ -0,0 +1,91 @@ +#include <stdio.h> +#include <string.h> + +static int CheckParams(double* vector, int length, char** chr, char* destination); + +void avpr(double *vector, int length, char* chr, int option, char* destination) +{ + char element[64]; + + /*Fill in default parameters.*/ + if (! CheckParams(vector, length, &chr, destination)) + { + return; + } + + /*Setup bl and el - some kind of beginning and terminating strings.*/ + char *bl = option ? "_{" : ""; + char *el = option ? "}" : ""; + + /*Destination defaults to an empty string.*/ + destination[0] = '\0'; + + /*Iterate through the elements in the vector, processing only nonzero + elements. The first nonzero element is processed differently than the others, + so use a flag to indicate whether the first nonzero element has been found or + not.*/ + int firstProcessed = 0; + int i; + for (i = 0; i < length; i++) + { + if (! vector[i]) continue; + if (! firstProcessed) + { + if (vector[i] == 1) + { + sprintf(element, "%s%s%d%s", chr, bl, i, el); + } + else if (vector[i] == -1) + { + sprintf(element, "-%s%s%d%s", chr, bl, i, el); + } + else + { + sprintf(element, "%g%s%s%d%s", vector[i], chr, bl, i, el); + } + firstProcessed = 1; + } + else + { + if (vector[i] == 1) + { + sprintf(element, "+%s%s%d%s", chr, bl, i, el); + } + else if (vector[i] > 0) + { + sprintf(element, "+%g%s%s%d%s", vector[i], chr, bl, i, el); + } + else if (vector[i] == -1) + { + sprintf(element, "-%s%s%d%s", chr, bl, i, el); + } + else + { + sprintf(element, "%g%s%s%d%s", vector[i], chr, bl, i, el); + } + } + strcat(destination, element); + } +} + +int CheckParams(double* vector, int length, char** chr, char* destination) +{ + /*vector and destination are both required.*/ + if (! (vector && destination)) + { + merror(0, "AVPR: A required pointer was null"); + return 0; + } + /*length cannot be non-positive.*/ + if (length < 1) + { + merror(0, "AVPR: Vector length is non-positive"); + return 0; + } + /*If the chr is 0, fill it with the default, m.*/ + if ((! *chr) || (! **chr )) + { + *chr = "m"; + } + return 1; +} \ No newline at end of file Modified: spnbox/spnbox.h =================================================================== --- spnbox/spnbox.h 2009-07-23 21:37:10 UTC (rev 201) +++ spnbox/spnbox.h 2009-07-24 03:38:40 UTC (rev 202) @@ -931,4 +931,29 @@ to the total number of places represented by Dm/Dp. Further, if M is present, its size must be appropriate (same number of rows as there are dependent places, same number of columns as there are independent places).*/ + +void avpr(double *vector, int length, char* chr, int option, char* destination); +/* +AVPR - Transforms a vector in a string to be used for displaying +equations/inequalities. + +[str] = avpr(x) + +Use the format below to specify the variable name in var (default name +is 'm'). + +[str] = avpr(x,var) + +Use the format below to generate a tex description with indices + +[str] = avpr(x,var,1) + +Written for Matlab by Marian V. Iordache, mar...@le.... +Converted to C by Marian V. Iordache and Stephen Camp, ste...@le.... + +C Usage: Parameters have the same meaning and names as in Matlab, with the +addition of the destination parameter, a pointer to a character array that will +be filled with the result. The array is not checked to make sure it has enough +space; this is left to the caller. +If chr is a null pointer it will default to m, as in Matlab.*/ #endif Modified: spnbox/tests/Makefile =================================================================== --- spnbox/tests/Makefile 2009-07-23 21:37:10 UTC (rev 201) +++ spnbox/tests/Makefile 2009-07-24 03:38:40 UTC (rev 202) @@ -10,6 +10,7 @@ COMMON=StructuredIO.o test.o MemoryManager.o general.o pns.o matrix.o matrixmath.o deallocation.o #These symbols define the dependencies of various test executables. +AVPR=avpr.o EXTENDEDMATRIX=extendedmatrix.o IPSLV=ipslv.o ../liblpsolve55.a IPSOLVE=ipsolve.o $(IPSLV) @@ -32,7 +33,9 @@ COMMONHEADER=../spnbox.h test.h ../../pnheaders/pns.h ../../pnheaders/matrix.h ../matrixmath.h ../MemoryManager.h StructuredIO.h #Targets -all: extendedmatrix ipslv ipsolve isadm issiph msplit matrixmath pn2acpn supervis actn ilpadm linenf nltrans pn2eacpn reduce tactn +all: avpr extendedmatrix ipslv ipsolve isadm issiph msplit matrixmath pn2acpn supervis actn admcon asiph ilpadm linenf nltrans pn2eacpn reduce tactn +avpr: test-avpr.o $(AVPR) $(COMMON) + $(COMPILER) -o avpr.exe test-avpr.o $(AVPR) $(COMMON) extendedmatrix: test-extendedmatrix.o $(EXTENDEDMATRIX) $(COMMON) $(COMPILER) -o extendedmatrix.exe test-extendedmatrix.o $(EXTENDEDMATRIX) $(COMMON) ipslv: test-ipslv.o $(IPSLV) @@ -79,6 +82,8 @@ $(COMPILER) -c ../admcon.c asiph.o: ../asiph.c ../spnbox.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../extendedmatrix.h ../MemoryManager.h $(COMPILER) -c ../asiph.c +avpr.o: ../avpr.c + $(COMPILER) -c ../avpr.c chkcons.o: ../spnbox.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../chkcons.c $(COMPILER) -c ../chkcons.c deallocation.o: ../deallocation.c ../spnbox.h @@ -133,6 +138,8 @@ $(COMPILER) -c test-admcon.c test-asiph.o: test-asiph.c $(COMMONHEADER) $(COMPILER) -c test-asiph.c +test-avpr.o: test-avpr.c $(COMMONHEADER) + $(COMPILER) -c test-avpr.c test-extendedmatrix.o: test-extendedmatrix.c $(COMMONHEADER) $(COMPILER) -c test-extendedmatrix.c test-ilpadm.o: test-ilpadm.c $(COMMONHEADER) Added: spnbox/tests/test-avpr.c =================================================================== --- spnbox/tests/test-avpr.c (rev 0) +++ spnbox/tests/test-avpr.c 2009-07-24 03:38:40 UTC (rev 202) @@ -0,0 +1,44 @@ +#include "test.h" + +int main(int argc, char* argv[]) +{ + char iDesc[] = "arrayd vector, string chr, int option, int maxlength"; + double* vector = 0; + int vLength = 0, option = 0, maxlength = 256; + char *destination; + char chr[128] = ""; + int *iFill; + + FILE* file; + + if (! (file = ParseCmdLine(argc, argv))) + { + return 0; + } + + MemoryManager mem = CreateMemoryManager(3, 0, 0, 0); + + while (ParseStructure(file, iDesc, &iFill, &mem, &vector, &vLength, chr, &option, &maxlength)) + { + DisplayStructure(iDesc, iFill, vector, vLength, chr, option, maxlength); + + if (maxlength < 2 || maxlength > 5000) maxlength = 256; + destination = mcalloc(&mem, maxlength, sizeof(char)); + + avpr(vector, vLength, chr, option, destination); + + printf("Result:\n%s\n", destination); + + FreeMemory(&mem); + mem = CreateMemoryManager(3, 0, 0, 0); + + vector = 0; + vLength = 0; + option = 0; + maxlength = 256; + chr[0] = '\0'; + printf("-------------------------------------------------------------------------------\n"); + } + return 1; +} + \ No newline at end of file Added: spnbox/tests/test-avpr.txt =================================================================== --- spnbox/tests/test-avpr.txt (rev 0) +++ spnbox/tests/test-avpr.txt 2009-07-24 03:38:40 UTC (rev 202) @@ -0,0 +1,59 @@ +echo Problem 1. +echo Solution should be: +echo <empty string> +vector 1 +0 +done + +echo Problem 2. +echo Solution should be: +echo m0 +vector 1 +1 +done + +echo Problem 3. +echo Solution should be: +echo -m0 +vector 1 +-1 +done + +echo Problem 4. +echo Solution should be: +echo 2m0 +vector 1 +2 +done + +echo Problem 5 +echo Solution should be: +echo -2m0 +vector 1 +-2 +done + +echo Problem 6 +echo Solution should be: +echo -2m0-m1+m3+2m4 +vector 5 +-2 -1 0 1 2 +done + +echo Problem 7 +echo Solution should be: +echo -2.5z0-z1+z3+2.5z4 +vector 5 +-2.5 -1 0 1 2.5 +chr z +done + +echo Problem 8 +echo Solution should be: +echo -2.5m_{0}-m_{1}+m_{3}+2.5m_{4} +vector 5 +-2.5 -1 0 1 2.5 +option 1 +done +quit + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-23 21:37:25
|
Revision: 201 http://pntool.svn.sourceforge.net/pntool/?rev=201&view=rev Author: StephenCamp Date: 2009-07-23 21:37:10 +0000 (Thu, 23 Jul 2009) Log Message: ----------- admcon has been implemented and amdcon.c compiles correctly. Test routines have been written and they compile correctly. admcon has NOT BEEN TESTED or debugged yet. The appropriate additions have been made to deallocation.c, spnbox.h, and the makefiles. Additionally, a bug in the test makefile has been corrected. Modified Paths: -------------- spnbox/Makefile spnbox/deallocation.c spnbox/spnbox.h spnbox/tests/Makefile Added Paths: ----------- spnbox/admcon.c spnbox/tests/test-admcon.c Modified: spnbox/Makefile =================================================================== --- spnbox/Makefile 2009-07-22 00:37:02 UTC (rev 200) +++ spnbox/Makefile 2009-07-23 21:37:10 UTC (rev 201) @@ -3,11 +3,17 @@ COMPILER=gcc -g -all: actn.o chkcons.o extendedmatrix.o ilpadm.o ipslv.o ipsolve.o isadm.o issiph.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a +all: actn.o admcon.o asiph.o chkcons.o deallocation.o extendedmatrix.o ilpadm.o ipslv.o ipsolve.o isadm.o issiph.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a actn.o: actn.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c actn.c +admcon.o: admcon.c spnbox.h matrixmath.h extendedmatrix.h ../pnheaders/general.h ../pnheaders/matrix.h + $(COMPILER) -c admcon.c + +asiph.o: asiph.c spnbox.h extendedmatrix.h ../pnheaders/general.h ../pnheaders/matrix.h + $(COMPILER) -c asiph.c + chkcons.o: chkcons.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h $(COMPILER) -c chkcons.c @@ -29,8 +35,8 @@ isadm.o: isadm.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c isadm.c -issiph.o: ../issiph.c ../spnbox.h ../../pnheaders/general.h ../../pnheaders/matrix.h - $(COMPILER) -c ../issiph.c +issiph.o: issiph.c spnbox.h ../pnheaders/general.h ../pnheaders/matrix.h + $(COMPILER) -c issiph.c linenf.o: linenf.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c linenf.c @@ -66,9 +72,9 @@ cd ../third-party/lp_solve_5.5; make -f Makefile.Linux lib clean: - rm -f *.o *.a + rm -fv *.o *.a cd ../third-party/lp_solve_5.5; make -f Makefile.Linux clean clean-partial: - rm -f *.o + rm -fv *.o Added: spnbox/admcon.c =================================================================== --- spnbox/admcon.c (rev 0) +++ spnbox/admcon.c 2009-07-23 21:37:10 UTC (rev 201) @@ -0,0 +1,610 @@ +#include <stdlib.h> +#include "../pnheaders/general.h" +#include "../pnheaders/matrix.h" +#include "MemoryManager.h" +#include "matrixmath.h" +#include "extendedmatrix.h" +#include "spnbox.h" + +static int CheckParams(admcon_p *params); +static int GetRowCount(admcon_p *params); +static matrix BuildZ(admcon_p *params); +static matrix BuildDX(admcon_p *p, admcon_r *result, matrix *Z); +static int *nlplace(admcon_p *p, matrix *DX, int *pCount); +static ipsolve_r RawSolution(admcon_p *param, matrix *DX, int* p, int pCount); +static admcon_r BuildResult(ipsolve_r *lpresult, int *p, int pCount, int rowCount); + +admcon_r admcon(admcon_p *params) +{ + /*Initialize to an error value.*/ + admcon_r result; + memset(&result, 0, sizeof(result)); + + /*Check parameters.*/ + if (! CheckParams(params)) + { + return result; + } + + /*Initialize the result to a default value.*/ + if (params->siphon) + { + result.l = tcalloc(NumberOfRows(params->Dm), sizeof(int)); + memcpy(result.l, params->siphon, sizeof(int) * NumberOfRows(params->Dm)); + } + result.how = 1; + + /*Get the row count and the intermediate matrix Z.*/ + int rowCount = GetRowCount(params); + matrix Z = BuildZ(params); + /*Get the intermediate linear programming matrix DX. Z will be deallocated + by the function call. + If DX returns an empty matrix, it means that the current solution is + feasible. Return immediately.*/ + matrix DX = BuildDX(params, &result, &Z); + if (! DX.type) return result; + + /*Get p, a list of places. This function is an aggregate of the nlplace function + present in the Matlab version of this function, and several lines of code + immediately after it. If nlplace returns a null pointer, it means that no + feasible solution exists.*/ + int pCount; + int *p; + if (! (p = nlplace(params, &DX, &pCount))) + { + memset(&result, 0, sizeof(admcon_r)); + DeallocateMatrix(&DX); + return result; + } + + /*Otherwise, proceed to build and solve another linear programming problem + using p. This problem deallocates DX.*/ + ipsolve_r lpresult = RawSolution(params, &DX, p, pCount); + + /*Get the new solution (Deallocate the space used by the old first)*/ + free(result.l); + return BuildResult(&lpresult, p, pCount, rowCount); +} + +/******************************************************************************* +This function processes the solution returned by RawSolution to build the new +solution. It also deallocates everything that still needs to be deallocated.*/ +admcon_r BuildResult(ipsolve_r *lpresult, int *p, int pCount, int rowCount) +{ + int i; + admcon_r result; + + /*If the lp solution is valid, copy the appropriate values to the result. + Otherwise leave it blank.*/ + if (! strcmp(lpresult->mhow, HOW_OK)) + { + result.l = tcalloc(rowCount, sizeof(int)); + result.lCount = rowCount; + for (i = 0; i < pCount; i++) + { + result.l[p[i]] = (int) lpresult->res[p[i]]; + } + result.how = 1; + } + else + { + memset(&result, 0, sizeof(admcon_r)); + } + + /*Deallocate p and the lpresult.*/ + free(p); + DeallocateIpsolve(lpresult); + return result; +} + +/******************************************************************************* +This function builds and solves a linear programming problem to get the modified +solution vector l. It returns the raw ipsolve results - not the processed +version that is the final solution. It also deallocates DX, which is not used +after this point.*/ +ipsolve_r RawSolution(admcon_p *param, matrix *DX, int* p, int pCount) +{ + MemoryManager mem; + mem = CreateMemoryManager(3, 1, 0, 0); + /*The constraint matrix is an identity followed below by those columns + of DX which have indices present in p. We will do this by adding rows directly + to DX (it has been optimized for row ops). nulling out the columns we are not + interested in, and putting in 1s for the identity where we are interested.*/ + InsertNullRows(DX, 0, pCount, -1); + ManageMatrix(&mem, DX); + + /*Insert the 1s we are interested in. While doing it, build a flag array that + is set at each index present in p.*/ + int *pFlag = mcalloc(&mem, NumberOfColumns(*DX), sizeof(int)); + int i, j; + for (i = 0; i < pCount; i++) + { + pFlag[p[i]] = 1; + SetMatrixEl(DX, i, p[i], 1); + } + /*Now go back and zero all the columns not flagged in pFlag.*/ + for (i = 0; i < NumberOfColumns(*DX); i++) + { + if (! pFlag[i]) MakeZeroColumn(DX, i); + } + + /*The constraint vector should be 1s for each row that was added by the + identity and zeros for all elements thereafter except the last.*/ + double *B = mcalloc(&mem, NumberOfRows(*DX), sizeof(double)); + for (i = 0; i < pCount; i++) + { + B[i] = 1; + } + B[NumberOfRows(*DX) - 1] = 1; + + /*Cost should have, for each place indexed in p, an element that is the sum + of all elements of Dm for that place that correspond to elements of the + incidence matrix D that are negative.*/ + double *F = mcalloc(&mem, NumberOfColumns(*DX), sizeof(double)); + for (i = 0; i < pCount; i++) + { + for (j = 0; j < NumberOfColumns(param->Dm); j++) + { + int dm = GetMatrixEl(¶m->Dm, p[i], j); + int dp = GetMatrixEl(¶m->Dp, p[i], j); + if (dm - dp < 0) F[p[i]] += (double) dm; + } + } + + /*Solve the problem.*/ + ipsolve_r result = ipsolve(DX, B, F, 0, 0, 0, 0); + + /*Free memory and return the solution.*/ + FreeMemory(&mem); + return result; +} + +/******************************************************************************* +Get the list of places p that are live. Return the list length in the integer +pointed to by parameter pCount.*/ +int *nlplace(admcon_p *p, matrix *DX, int *pCount) +{ + MemoryManager mem; + mem = CreateMemoryManager(4, 1, 0, 0); + + /*We need to build a linear programming problem. We will iterate through each + column, adjust the problem slightly, and resolve it.*/ + + /*We need to know how many places are flagged in the siphon flag array.*/ + int placeCount = 0, i, j, k; + for (i = 0; i < NumberOfRows(p->Dm); i++) + { + if (p->siphon[i]) placeCount++; + } + + /*The constraint matrix is the columns (?) of DX for which flags are set in the + siphon listing, followed to the right by a negative identity, then below by a + vector which will change from iteration to iteration.*/ + matrix L; + MAllocateMatrixType(&mem, 2, &L, NumberOfRows(*DX) + 1, placeCount + NumberOfRows(*DX)); + j = 0; + /*Copy the appropriate columns of DX.*/ + for (i = 0; i < NumberOfRows(p->Dm); i++) + { + if (p->siphon[i]) + { + CopyBlock(NumberOfRows(*DX), 1, DX, 0, i, &L, 0, j++); + } + } + /*Fill in the negative identity.*/ + for (i = 0; i < NumberOfRows(*DX); i++) + { + SetMatrixEl(&L, i, i + placeCount, -1); + } + + /*The constraint vector should be all zeros except the last element, which + should be 1.*/ + double *B = mcalloc(&mem, NumberOfRows(L), sizeof(double)); + B[NumberOfRows(L) - 1] = 1; + + /*Cost vector should be all ones.*/ + double *F = mcalloc(&mem, NumberOfColumns(L), sizeof(double)); + for (i = 0; i < NumberOfColumns(L); i++) + { + F[i] = 1; + } + + /*Constraint type should be all equalities (0) except that of the last column, + which should be a greater-than (1).*/ + short *ctype = mcalloc(&mem, NumberOfRows(L), sizeof(short)); + ctype[NumberOfRows(L) - 1] = 1; + + /*IntList should be all zeroes.*/ + short *intList = mcalloc(&mem, NumberOfColumns(L), sizeof(short)); + + /*During our iterations we will modify a flag array, cov, with an element for + each of the columns that came from DX. Allocate space.*/ + int *cov = mcalloc(&mem, placeCount, sizeof(short)); + + /*Start the iterations. Store in j the index of the last column of L such that + its element in the last row was set to 1 within the loop. -1 means no column + set yet.*/ + j = -1; + for (i = 0; i < placeCount; i++) + { + /*Process only columns which are not flagged yet in cov.*/ + if (cov[i]) continue; + + /*The last row of the constraint matrix should be all zeros except for the + element corresponding to the current column, which should be 1.*/ + if (j >= 0) SetMatrixEl(&L, NumberOfRows(L) - 1, j, 0); + j = i; + SetMatrixEl(&L, NumberOfRows(L) - 1, i, 1); + + /*Solve the linear programming problem. Let the bounds default to 0 and inf.*/ + ipsolve_r lpresult = ipsolve(&L, B, F, intList, 0, 0, ctype); + + /*If the solution is valid, set any elements of cov for which there is a + nonzero (and not very small) value in the solution vector.*/ + if (! strcmp(lpresult.mhow, HOW_OK)) + { + for (k = 0; k < placeCount; k++) + { + if (lpresult.res[k] > HOW_MAX_ERROR || lpresult.res[k] < -HOW_MAX_ERROR) + { + cov[k] = 1; + } + } + } + /*Deallocate any memory used by the solution.*/ + DeallocateIpsolve(&lpresult); + } + + /*Build the result. It is a list of the indices of elements of the siphon list + (places) that correspond to nonzero elements in cov. Start by counting them.*/ + *pCount = 0; + for (i = 0; i < placeCount; i++) + { + if (cov[i]) (*pCount)++; + } + /*Allocate space and do the building. Each index should be not the index + within cov, but, for the ith element of cov, the index of the ith nonzero + element in siphon. Use j to count indices in siphon.*/ + int *result = tcalloc(*pCount, sizeof(int)); + j = -1; + k = 0; + for (i = 0; i < placeCount; i++) + { + /*Find the ith nonzero place in siphon.*/ + j++; + while (! p->siphon[j]) j++; + /*If the current nonzero place is flagged in cov, copy the index.*/ + if (cov[i]) result[k++] = j; + } + /*Free up memory.*/ + FreeMemory(&mem); + + /*Make sure that there are at least two places with indices in p that are + also present in the active place list. Count places like that in k.*/ + k = 0; + for (i = 0; i < *pCount; i++) + { + for (j = 0; j < p->apCount; j++) + { + if (result[i] == p->apl[j]) + { + if (++k == 2) break; + } + } + } + /*If not, no feasible solution to the admcon problem exists. Return a null + pointer to indicate this.*/ + if (k < 2) + { + free(result); + *pCount = 0; + return 0; + } + return result; +} + +/******************************************************************************* +This function builds the intermediate linear programming description matrix DX. +It runs a test on DX, and if the value of l (the solution vector) is already +correct it returns an empty matrix to signify that admcon should return +immediately. This function also deallocates the Z matrix, which, is not used +again.*/ +matrix BuildDX(admcon_p *p, admcon_r *result, matrix *Z) +{ + /*DX is a matrix composed of a right-to-left concatentation of submatrices: + DX = [Auc, Auo, -Auo, -Ds, d] + For: + Auc = Z * DI(:,Tuc) + Auo = Z * DI(:,Tuo) + Ds = (Dp - Dm)(:,ntr) %that is, the part of the incidence matrix corresponding + %to transitions that came from transition split. + d = a flag array, one for each place, set to 1 for active places. + */ + /*Allocate DX.*/ + matrix DX; + AllocateMatrixType(2, &DX, NumberOfRows(*Z), p->TucCount + p->TuoCount + p->TuoCount + p->ntCount + 1); + + int i, j, k; + for (i = 0; i < NumberOfRows(DX); i++) + { + /*Fill in Auc.*/ + for (j = 0; j < p->TucCount; j++) + { + SetMatrixEl(&DX, i, j, MultiplyVector(Z, &p->DI, i, p->Tuc[j], 0)); + } + /*Fill in Auo and -Auo.*/ + for (j = 0; j < p->TuoCount; j++) + { + k = MultiplyVector(Z, &p->DI, i, p->Tuo[j], 0); + SetMatrixEl(&DX, i, j + p->TucCount, k); + SetMatrixEl(&DX, i, j + p->TucCount + p->TuoCount, -k); + } + /*Fill in -Ds.*/ + for (j = 0; j < p->ntCount; j++) + { + k = GetMatrixEl(&p->Dm, i, p->ntr[j]) - GetMatrixEl(&p->Dp, i, p->ntr[j]); + SetMatrixEl(&DX, i, j + p->TucCount + (2 * p->TuoCount), k); + } + } + /*Fill in d.*/ + for (i = 0; i < p->apCount; p++) + { + SetMatrixEl(&DX, p->apl[i], NumberOfColumns(DX) - 1, 1); + } + /*Deallocate Z. It will not be needed anymore.*/ + DeallocateMatrix(Z); + + /*Run a test. If DX * l (the current solution vector) >= b, the current + solution vector is good. b should be a vector of all zeros except for the last + element, which should be 1. We can skip the building of b and simply put the + test in a loop.*/ + for (i = 0; i < NumberOfRows(DX); i++) + { + k = MultiplyVector(&DX, (matrix*) result->l, i, MULTIPLYVECTOR_ARRAY, 0); + if (k < (i < NumberOfRows(DX) - 1 ? 0 : 1)) + { + break; + } + } + /*If we made it through the loop without breaking out early, it means that the + current solution vector is valid. Deallocate and zero DX and return to + indicate this. Otherwise just return DX as-is for the next stage in + processing.*/ + if (i == NumberOfRows(DX)) + { + DeallocateMatrix(&DX); + } + return DX; +} + +/******************************************************************************* +This function builds the matrix Z, an intermediate matrix of the admcon +algorithm.*/ +matrix BuildZ(admcon_p *p) +{ + /*Build the independent place flag array. This is an array of flags, one for + each element of the independent place list. The flag should be set of the + place indexed by the corresponding ind. place list element is also present in + the original place list.*/ + int *ipFlag = 0; + int ipFlagged = 0, i, j, k; + if (p->ipl) + { + ipFlag = tcalloc(p->ipCount, sizeof(int)); + for (i = 0; i < p->ipCount; i++) + { + for (j = 0; j < p->opCount; j++) + { + if (p->ipl[i] == p->opl[j]) + { + ipFlag[i] = 1; + ipFlagged++; + break; + } + } + } + } + + /*Initialize the result to an empty matrix.*/ + matrix result; + memset(&result, 0, sizeof(matrix)); + + if (ipFlagged) + { + /*Allocate space for Z.*/ + AllocateMatrixType(2, &result, p->ipCount + p->dpCount, ipFlagged); + j = 0; + /*Build Z. We'll need to examine each independent place.*/ + for (i = 0; i < p->ipCount; i++) + { + if (ipFlag[i]) + { + /*Build the part of Z based on independent places. We are inserting an + identity, except that some columns (those not flagged in ipFlagged) must + be removed premptively. Thus, on the ith independent place, count how + many places up to that point have been flagged. Use j. Set the jth + column of Z (at the appropriate row) to a 1.*/ + SetMatrixEl(&result, p->ipl[i], j, 1); + + /*Build the part of Z based on dependent places. We are copying rows + from M to their corresponding rows in Z (dep. place rows) except that + the columns not flagged in ipFlag will not be copied.*/ + if (p->M.type) + { + for (k = 0; k < p->dpCount; k++) + { + SetMatrixEl(&result, p->dpl[k], j, GetMatrixEl(&p->M, i, k)); + } + } + + j++; + } + } + } + /*Free the flag array.*/ + if (ipFlag) free(ipFlag); + return result; +} + +/******************************************************************************* +This function gets the row count.*/ +int GetRowCount(admcon_p *params) +{ + int max = 0, i; + for (i = 0; i < params->ipCount; i++) + { + if (params->ipl[i] > max) max = params->ipl[i]; + } + for (i = 0; i < params->dpCount; i++) + { + if (params->dpl[i] > max) max = params->dpl[i]; + } + for (i = 0; i < params->opCount; i++) + { + if (params->opl[i] > max) max = params->opl[i]; + } + return max; +} + +/******************************************************************************* +This function checks the parameters to make sure they are valid.*/ +int CheckParams(admcon_p *params) +{ + /*If the skipParamCheck flag is set, skip the checks. Return 1 immediately.*/ + if (params->skipParamCheck) return 1; + + int i, j; + if (! params) + { + merror(0, "ADMCON: No parameters provided"); + return 0; + } + /*Dm and Dp must be present.*/ + if (! (params->Dm.type && params->Dp.type)) + { + merror(0, "ADMCON: Dm and Dp were not initialized"); + return 0; + } + /*Dm and Dp must be the same size.*/ + if (NumberOfRows(params->Dm) != NumberOfRows(params->Dp) || NumberOfColumns(params->Dm) != NumberOfColumns(params->Dp)) + { + merror(0, "ADMCON: Dm and Dp are not the same size"); + return 0; + } + /*DI must be present.*/ + if (! params->DI.type) + { + merror(0, "ADMCON: DI has not been initialized"); + return 0; + } + /*Make sure that array pointers are null if their counts are null.*/ + if (! params->ipCount) params->ipl = 0; + else if (! params->ipl) params->ipCount = 0; + if (! params->dpCount) params->dpl = 0; + else if (! params->dpl) params->dpCount = 0; + if (! params->opCount) params->opl = 0; + else if (! params->opl) params->opCount = 0; + if (! params->apCount) params->apl = 0; + else if (! params->apl) params->apCount = 0; + if (! params->ntCount) params->ntr = 0; + else if (! params->ntr) params->ntCount = 0; + if (! params->TucCount) params->Tuc = 0; + else if (! params->Tuc) params->TucCount = 0; + if (! params->TuoCount) params->Tuo = 0; + else if (! params->Tuo) params->TuoCount = 0; + + /*If the dependent/independent place lists are provided, run some tests.*/ + if (params->ipl || params->dpl) + { + /*Their total count must be that of the total number of places.*/ + if (params->ipCount + params->dpCount != NumberOfRows(params->Dm)) + { + merror(0, "ADMCON: The number of dependent and independent places does not match the total number of places"); + return 0; + } + /*They cannot include any of the same places or include any out-of-range + indices.*/ + for (i = 0; i < params->ipCount; i++) + { + if (params->ipl[i] < 0 || params->ipl[i] > NumberOfRows(params->Dm)) + { + merror(0, "ADMCON: The independent place list has an out-of-range index"); + return 0; + } + } + for (i = 0; i < params->dpCount; i++) + { + if (params->dpl[i] < 0 || params->dpl[i] > NumberOfRows(params->Dm)) + { + merror(0, "ADMCON: The dependent place list has an out-of-range index"); + return 0; + } + } + for (i = 0; i < params->ipCount; i++) + { + for (j = 0; j < params->dpCount; j++) + { + if (params->ipl[i] == params->dpl[j]) + { + merror(0, "ADMCON: The independent and dependent place lists contain common elements"); + return 0; + } + } + } + } + /*If the list of transitions that resulted from the transition split is present, + make sure there are no duplicate or out-of-range elements.*/ + if (params->ntr) + { + for (i = 0; i < params->ntCount; i++) + { + if (params->ntr[i] < 0 || params->ntr[i] > NumberOfColumns(params->Dm)) + { + merror(0, "ADMCON: The new transition list contains an out-of-range index"); + return 0; + } + for (j = i + 1; j < params->ntCount; j++) + { + if (params->ntr[i] == params->ntr[j]) + { + merror(0, "ADMCON: The new transition list containts duplicate entries"); + } + } + } + } + /*If M is present (nonzero) it must have the same number of columns as there + are independent places and the same number of rows as there are independent + places.*/ + if (params->M.type && (params->ipl && params->dpl)) + { + if (NumberOfColumns(params->M) != params->ipCount || NumberOfRows(params->M) != params->dpCount) + { + merror(0, "The dependent-to-independent marking transformation matrix is not the right size"); + return 0; + } + } + /*At least one of Tuc or Tuo must be provided.*/ + if (! (params->Tuc || params->Tuo)) + { + merror(0, "ADMCON: No unobservable or uncontrollable transitions were given"); + return 0; + } + /*Neither Tuc nor Tuo should contain duplicate or out-of-range indices.*/ + for (i = 0; i < params->TucCount; i++) + { + if (params->Tuc[i] < 0 || params->Tuc[i] >= NumberOfColumns(params->DI)) + { + merror(0, "ADMCON: Tuc contains an out-of-range index"); + return 0; + } + } + for (i = 0; i < params->TuoCount; i++) + { + if (params->Tuo[i] < 0 || params->Tuo[i] >= NumberOfColumns(params->DI)) + { + merror(0, "ADMCON: Tuo contains an out-of-range index"); + return 0; + } + } + return 1; +} Modified: spnbox/deallocation.c =================================================================== --- spnbox/deallocation.c 2009-07-22 00:37:02 UTC (rev 200) +++ spnbox/deallocation.c 2009-07-23 21:37:10 UTC (rev 201) @@ -156,3 +156,8 @@ FreeMatrixSafe(&data->MS); FreeMatrixSafe(&data->NMS); } + +void DeallocateAdmcon(admcon_r *data) +{ + FreeMemorySafe(data->l); +} Modified: spnbox/spnbox.h =================================================================== --- spnbox/spnbox.h 2009-07-22 00:37:02 UTC (rev 200) +++ spnbox/spnbox.h 2009-07-23 21:37:10 UTC (rev 201) @@ -180,6 +180,15 @@ matrix NMS; } asiph_r; +typedef struct admcon_r +{ + /*A flag vector and its length.*/ + int *l; + int lCount; + /*A flag. If set, we found an admissible constraint.*/ + int how; +} admcon_r; + /*Functions to free return structures. Implemented in deallocation.c*/ void DeallocateSupervis(supervis_r *data); void DeallocateIpslv(ipslv_r *data); @@ -196,6 +205,7 @@ void DeallocateTactn(tactn_r *data); void DeallocateIssiph(issiph_r *data); void DeallocateAsiph(asiph_r *data); +void DeallocateAdmcon(admcon_r *data); /*Constants returned in by functions to indicate the nature of the result.*/ #define HOW_ERROR "error" @@ -842,4 +852,83 @@ to an integer array containing the indices in the list followed by a single integer, listCount, that should be set to the length of the list. */ + +/*These are the parameters for a call to admcon.*/ +typedef struct admcon_p +{ + /*The place flag array indicating which places are part of the siphon.*/ + int* siphon; + /*The input and output matrices of the Petri net as well as the incidence + matrix of the target petri net.*/ + matrix Dm, Dp, DI; + /*The lists of indendent, dependent, original places, and active places.*/ + int *ipl, *dpl, *opl, *apl; + int ipCount, dpCount, opCount, apCount; + /*The list of transitions that resulted from the transition split.*/ + int *ntr; + int ntCount; + /*The transformation matrix fron independent to dependent marking.*/ + matrix M; + /*The lists of unobservable and uncontrollable transitions.*/ + int *Tuc, *Tuo; + int TucCount, TuoCount; + int skipParamCheck; +} admcon_p; + +admcon_r admcon(admcon_p *params); +/*ADMCON - A procedure to find admissible constraints for siphon control + +[a, how] = admcon(s_list, Dm, Dp, ipl, dpl, opl, apl, ntr, M, Tuc, Tuo, Di) + +s_list: s_list(i) = 1 if place i is in the siphon, else 0. (Place i +has the index i in the incidence matrix D.) + +Dm and Dp: the input and output incidence matrices of the Petri net +(places -> rows and transitions -> columns.) + +ipl, dpl, opl: the set of independent, dependent and original places. + +apl: the set of places of the active subnet. + +ntr: the set of new transitions (those resulted through transition split). + +M: the matrix expressing the marking of dpl in terms of that of ipl. + +Tuc, Tuo: the sets of the uncontrollable and unobservable transitions +of the original (target) Petri net. + +Di: the incidence matrix of the target Petri net; Tuc, Tuo are specified +with respect to Di. + +For unspecified arguments, use the empty array []. + +a - is a vector such that a'*m >= 1 is admissible. + +how - is set to 0 if no admissible constraint could be found. + +Written for Matlab by Marian V. Iordache, mar...@le.... +Converted to C by Marian V. Iordache and Stephen Camp, ste...@le.... + +C Usage: +The admcon function takes a pointer to a structure of type admcon_p, which +contains parts for all the parameters required by admcon, followed by one +additional parameter, skipParamCheck. If skipParamCheck is nonzero, admcon will +endeavor to speed its operations slightly by skipping the parameter check +routines. Note that the calling routine must take responsibility for properly +formatting all parameters. + +The parameters have the same names and meanings except for Matlab s_list, which +is equivalent to C siphon. +siphon should point to an array of integers, one for each place in Dm/Dp. +Dm, Dp, and DI have the same usage and meaning in C and Matlab. +The lists of indices ipl, dpl, opl, apl, ntr, Tuc, and Tuo should be given as +pointers to arrays of integers. For each array, there is also a count variable, +which should be set to the length of the array. No arrays should contain +duplicate elements or indices to transitions. + +Dm, Dp, DI, and at least one of Tuc or Tuo is required. +If the dependent and independent place lists are present, their counts must sum +to the total number of places represented by Dm/Dp. Further, if M is present, its +size must be appropriate (same number of rows as there are dependent places, same +number of columns as there are independent places).*/ #endif Modified: spnbox/tests/Makefile =================================================================== --- spnbox/tests/Makefile 2009-07-22 00:37:02 UTC (rev 200) +++ spnbox/tests/Makefile 2009-07-23 21:37:10 UTC (rev 201) @@ -19,6 +19,7 @@ PN2ACPN=pn2acpn.o SUPERVIS=supervis.o $(EXTENDEDMATRIX) ACTN=actn.o $(NLTRANS) +ADMCON=admcon.o $(EXTENDEDMATRIX) $(IPSOLVE) ASIPH=asiph.o $(ACTN) $(EXTENDEDMATRIX) ILPADM=ilpadm.o $(IPSOLVE) LINENF=linenf.o $(ILPADM) @@ -48,10 +49,12 @@ $(COMPILER) -o matrixmath.exe test-matrixmath.o $(COMMON) pn2acpn: test-pn2acpn.o $(COMMON) $(PN2ACPN) $(COMPILER) -o pn2acpn.exe test-pn2acpn.o $(COMMON) $(PN2ACPN) -supervis: test-supervis.o $(COMMON) $(EXTENDEDMATRIX) $(SUPERVIS) - $(COMPILER) -o supervis.exe test-supervis.o $(COMMON) $(EXTENDEDMATRIX) $(SUPERVIS) +supervis: test-supervis.o $(COMMON) $(SUPERVIS) + $(COMPILER) -o supervis.exe test-supervis.o $(COMMON) $(SUPERVIS) actn: test-actn.o $(COMMON) $(ACTN) $(COMPILER) -o actn.exe test-actn.o $(COMMON) $(ACTN) +admcon: test-admcon.o $(COMMON) $(ADMCON) + $(COMPILER) -o admcon.exe test-admcon.o $(COMMON) $(ADMCON) asiph: test-asiph.o $(COMMON) $(ASIPH) $(COMPILER) -o asiph.exe test-asiph.o $(COMMON) $(ASIPH) ilpadm: test-ilpadm.o $(COMMON) $(ILPADM) @@ -67,13 +70,13 @@ tactn: test-tactn.o $(COMMON) $(TACTN) $(COMPILER) -o tactn.exe test-tactn.o $(COMMON) $(TACTN) clean: - rm -f *.o - rm -f *.exe - rm -f *.stackdump + rm -fv *.o *.exe *.stackdump #Rules for making the general object files. actn.o: ../actn.c ../spnbox.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../matrixmath.h ../MemoryManager.h $(COMPILER) -c ../actn.c +admcon.o: ../admcon.c ../spnbox.h ../matrixmath.h ../extendedmatrix.h ../../pnheaders/general.h ../../pnheaders/matrix.h + $(COMPILER) -c ../admcon.c asiph.o: ../asiph.c ../spnbox.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../extendedmatrix.h ../MemoryManager.h $(COMPILER) -c ../asiph.c chkcons.o: ../spnbox.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../chkcons.c @@ -84,7 +87,7 @@ $(COMPILER) -c ../extendedmatrix.c general.o: ../../pnheaders/general.c ../../pnheaders/general.h $(COMPILER) -c ../../pnheaders/general.c -ilpadm.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../ilpadm.c +ilpadm.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../ilpadm.c $(COMPILER) -c ../ilpadm.c isadm.o: ../isadm.c ../spnbox.h ../../pnheaders/general.h ../MemoryManager.h ../../pnheaders/pns.h ../matrixmath.h $(COMPILER) -c ../isadm.c @@ -92,31 +95,31 @@ $(COMPILER) -c ../issiph.c ipslv.o: ../spnbox.h ../ipslv.c $(COMPILER) -c ../ipslv.c -ipsolve.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../ipsolve.c +ipsolve.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../ipsolve.c $(COMPILER) -c ../ipsolve.c -linenf.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../linenf.c +linenf.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../linenf.c $(COMPILER) -c ../linenf.c -matrix.o: ../../pnheaders/matrix.c ../../pnheaders/matrix.h ../../pnheaders/pns.h - $(COMPILER) -c ../../pnheaders/matrix.c -matrixmath.o: ../matrixmath.c ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h +matrix.o: ../../pnheaders/matrix.c ../../pnheaders/matrix.h ../../pnheaders/pns.h + $(COMPILER) -c ../../pnheaders/matrix.c +matrixmath.o: ../matrixmath.c ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h $(COMPILER) -c ../matrixmath.c -MemoryManager.o: ../MemoryManager.h ../MemoryManager.c ../../pnheaders/general.h ../../pnheaders/matrix.h +MemoryManager.o: ../MemoryManager.h ../MemoryManager.c ../../pnheaders/general.h ../../pnheaders/matrix.h $(COMPILER) -c ../MemoryManager.c -msplit.o: ../spnbox.h ../../pnheaders/matrix.h ../matrixmath.h ../MemoryManager.h ../msplit.c +msplit.o: ../spnbox.h ../../pnheaders/matrix.h ../matrixmath.h ../MemoryManager.h ../msplit.c $(COMPILER) -c ../msplit.c nltrans.o: ../nltrans.c ../spnbox.h ../../pnheaders/matrix.h ../matrixmath.h ../MemoryManager.h $(COMPILER) -c ../nltrans.c -pn2acpn.o: ../spnbox.h ../../pnheaders/matrix.h ../MemoryManager.h ../pn2acpn.c +pn2acpn.o: ../spnbox.h ../../pnheaders/matrix.h ../MemoryManager.h ../pn2acpn.c $(COMPILER) -c ../pn2acpn.c -pn2eacpn.o: ../spnbox.h ../../pnheaders/matrix.h ../MemoryManager.h ../pn2eacpn.c +pn2eacpn.o: ../spnbox.h ../../pnheaders/matrix.h ../MemoryManager.h ../pn2eacpn.c $(COMPILER) -c ../pn2eacpn.c -pns.o: ../../pnheaders/pns.c ../../pnheaders/pns.h ../../pnheaders/general.h ../../pnheaders/matrix.h - $(COMPILER) -c ../../pnheaders/pns.c -reduce.o: ../spnbox.h ../extendedmatrix.h ../../pnheaders/matrix.h ../reduce.c +pns.o: ../../pnheaders/pns.c ../../pnheaders/pns.h ../../pnheaders/general.h ../../pnheaders/matrix.h + $(COMPILER) -c ../../pnheaders/pns.c +reduce.o: ../spnbox.h ../extendedmatrix.h ../../pnheaders/matrix.h ../reduce.c $(COMPILER) -c ../reduce.c supervis.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/ ../../pnheaders/matrix.h ../supervis.c ../extendedmatrix.h $(COMPILER) -c ../supervis.c -StructuredIO.o: ../MemoryManager.h ../../pnheaders/matrix.h StructuredIO.h StructuredIO.c +StructuredIO.o: ../MemoryManager.h ../../pnheaders/matrix.h StructuredIO.h StructuredIO.c $(COMPILER) -c StructuredIO.c tactn.o: ../tactn.c ../spnbox.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../matrixmath.h ../MemoryManager.h $(COMPILER) -c ../tactn.c @@ -126,6 +129,8 @@ #Rules for making the test executable object files. test-actn.o: test-actn.c $(COMMONHEADER) $(COMPILER) -c test-actn.c +test-admcon.o: test-admcon.c $(COMMONHEADER) + $(COMPILER) -c test-admcon.c test-asiph.o: test-asiph.c $(COMMONHEADER) $(COMPILER) -c test-asiph.c test-extendedmatrix.o: test-extendedmatrix.c $(COMMONHEADER) Added: spnbox/tests/test-admcon.c =================================================================== --- spnbox/tests/test-admcon.c (rev 0) +++ spnbox/tests/test-admcon.c 2009-07-23 21:37:10 UTC (rev 201) @@ -0,0 +1,46 @@ +#include "test.h" + +int main(int argc, char* argv[]) +{ + char iDesc[] = "matrix D, matrix Dm, matrix Dp, matrix DI, indexarray Tuc, indexarray Tuo, arrayi siphon, arrayi ipl, arrayi dpl, arrayi opl, arrayi apl, arrayi ntr, matrix M, int SkipCheck"; + char oDesc[] = "arrayi l, int how"; + admcon_p params; + admcon_r result; + int *iFill; + int oFill[2] = {1, 1}; + FILE* input; + if (! (input = ParseCmdLine(argc, argv))) + { + return 0; + } + + MemoryManager mem = CreateMemoryManager(10, 5, 0, 0); + matrix D; + int dummy; + memset(¶ms, 0, sizeof(admcon_p)); + while (ParseStructure(input, iDesc, &iFill, &mem, &D, ¶ms.Dm, ¶ms.Dp, ¶ms.DI, ¶ms.Tuc, ¶ms.TucCount, ¶ms.Tuo, ¶ms.TuoCount, ¶ms.siphon, &dummy, ¶ms.ipl, ¶ms.ipCount, ¶ms.dpl, ¶ms.dpCount, ¶ms.opl, ¶ms.opCount, ¶ms.apl, ¶ms.apCount, ¶ms.ntr, ¶ms.ntCount, ¶ms.M, ¶ms.skipParamCheck)) + { + /*Display the problem.*/ + DisplayStructure(iDesc, iFill, &D, ¶ms.Dm, ¶ms.Dp, ¶ms.DI, params.Tuc, params.TucCount, iFill[3] ? NumberOfColumns(params.DI) : 0, params.Tuo, params.TuoCount, iFill[3] ? NumberOfColumns(params.DI) : 0, params.siphon, dummy, params.ipl, params.ipCount, params.dpl, params.dpCount, params.opl, params.opCount, params.apl, params.apCount, params.ntr, params.ntCount, params.M, params.skipParamCheck); + + /*Fill in Dm and Dp if necessary.*/ + FillDmDp(iFill, &D, ¶ms.Dm, ¶ms.Dp, &mem); + + /*Solve the problem.*/ + result = admcon(¶ms); + + /*Setup filled as appropriate.*/ + oFill[0] = result.how; + + /*Show the result.*/ + printf("Solution:\n"); + DisplayStructure(oDesc, oFill, result.l, result.how); + + /*Free memory.*/ + FreeMemory(&mem); + mem = CreateMemoryManager(10, 5, 0, 0); + DeallocateAdmcon(&result); + } + FreeMemory(&mem); + return 1; +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-22 00:37:09
|
Revision: 200 http://pntool.svn.sourceforge.net/pntool/?rev=200&view=rev Author: StephenCamp Date: 2009-07-22 00:37:02 +0000 (Wed, 22 Jul 2009) Log Message: ----------- asiph.c is implemented and passes all tests. Makefiles, spnbox.h, and deallocation.c have been modified as appropriate. Made some minor modifications to the routines in test.c. Modified Paths: -------------- spnbox/Makefile spnbox/deallocation.c spnbox/spnbox.h spnbox/tests/Makefile spnbox/tests/test.c Added Paths: ----------- spnbox/asiph.c spnbox/tests/test-asiph.c spnbox/tests/test-asiph.txt Modified: spnbox/Makefile =================================================================== --- spnbox/Makefile 2009-07-17 16:40:11 UTC (rev 199) +++ spnbox/Makefile 2009-07-22 00:37:02 UTC (rev 200) @@ -10,6 +10,9 @@ chkcons.o: chkcons.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h $(COMPILER) -c chkcons.c + +deallocation.o: deallocation.c spnbox.h ../pnheaders/matrix.h + $(COMPILER) -c deallocation.c extendedmatrix.o: extendedmatrix.c extendedmatrix.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c extendedmatrix.c Added: spnbox/asiph.c =================================================================== --- spnbox/asiph.c (rev 0) +++ spnbox/asiph.c 2009-07-22 00:37:02 UTC (rev 200) @@ -0,0 +1,887 @@ +#include <stdio.h> +#include "../pnheaders/general.h" +#include "../pnheaders/matrix.h" +#include "spnbox.h" +#include "MemoryManager.h" +#include "extendedmatrix.h" + +typedef struct asiph_data +{ + int *numInputPlaces; + int *curTrans; + int *counters; + matrix M; + matrix N; + matrix MT; + matrix NT; + matrix newRow; + matrix newPlace; + matrix MNS; + matrix NS; +} asiph_data; + +static int CheckParams(matrix *Dm, matrix *Dp, int **list, int *listCount, matrix *PS, matrix **Dma, matrix **Dpa, MemoryManager *mem); +static matrix SXInit(matrix *Dm, matrix *Dp, matrix *Dma, matrix* Dpa, matrix *PS, int **list, int* listCount, asiph_data* data); +static int* insert(asiph_data* data, matrix* vector, int* index); +static int *DataInit(matrix *Dm, matrix *Dp, matrix *PS, matrix *sx, asiph_data* data); +static int GetNewTrans(matrix *Dm, matrix *Dp, matrix *Places, int *Flags); +static void OuterLoopInit(asiph_data* data, matrix *Dm, matrix *Dp, MemoryManager *mem); +static void MiddleLoopInit(asiph_data* data, asiph_r* result, int siphon); +static void InnerLoopInit(asiph_data* data, matrix *Dm, matrix *Dp); +static int Check1(matrix *MNS, matrix *newRow); +static int Check2(matrix* M, matrix* newRow); +static int* DoInnerLoop(asiph_data* data, matrix* Dm, matrix *Dp, int* index); +static void PrintPercent(int num, int denom); +static asiph_r BuildResult(matrix *Dm, matrix *Dp, asiph_data* data, int *index); + +asiph_r asiph(matrix *Dm, matrix *Dp, int* list, int listCount, matrix *PS, matrix *Dma, matrix *Dpa) +{ + MemoryManager mem; + mem = CreateMemoryManager(10, 10, 0, 0); + asiph_r result; + memset(&result, 0, sizeof(asiph_r)); + /*Check parameters.*/ + if (! CheckParams(Dm, Dp, &list, &listCount, PS, &Dma, &Dpa, &mem)) + { + return result; + } + asiph_data data; + memset(&data, 0, sizeof(asiph_data)); + + /*Initialize sx (and a few other things)*/ + matrix sx = SXInit(Dm, Dp, Dma, Dpa, PS, &list, &listCount, &data); + ManageMatrix(&mem, &sx); + /*Initialize some other parts of the loop data. Build the newIndex array.*/ + int *newIndex = DataInit(Dm, Dp, PS, &sx, &data); + + /*Allocate and initialize various quantities that do not change or the space + for which does not change over the iterations of the outer loop.*/ + OuterLoopInit(&data, Dm, Dp, &mem); + + /*Iterate through each of the rows of NS. Each row corresponds to a siphon + that needs to be processed. If verbosity is high enough we'll be printing a + progress report as we go. Prepare.*/ + int siphon, originalSiphons; + originalSiphons = NumberOfRows(data.NS); + if (is_verbose() >= VRB_ASIPH) + { + printf("ASIPH: Primary Processing Loop Progress: "); + PrintPercent(0, 1); + } + for (siphon = 0; siphon < originalSiphons; siphon++) + { + /*Initialize the stuff that doesn't change within the middle loop.*/ + MiddleLoopInit(&data, &result, siphon); + /*The middle loop runs until we have removed all rows from M/N*/ + while (NumberOfRows(data.M)) + { + /*Initialize the stuff for the innermost loop run.*/ + InnerLoopInit(&data, Dm, Dp); + /*Run the inner loop. This has been moved to its own function.*/ + newIndex = DoInnerLoop(&data, Dm, Dp, newIndex); + /*Now concatenate MT onto M and NT onto N.*/ + if (NumberOfRows(data.MT)) InsertRows(&data.M, &data.MT, -1, -1); + if (NumberOfRows(data.NT)) InsertRows(&data.N, &data.NT, -1, -1); + /*Remove the first row of M and N.*/ + RemoveRows(&data.M, 0, 1, -1); + RemoveRows(&data.N, 0, 1, -1); + } + /*Deallocate whatever still needs to be deallocated - M and N.*/ + DeallocateMatrix(&data.M); + DeallocateMatrix(&data.N); + /*If verbosity is high enough, print a progress percentage.*/ + if (is_verbose() >= VRB_ASIPH) + { + PrintPercent(siphon + 1, originalSiphons); + } + } + if (is_verbose() >= VRB_ASIPH) + { + PrintPercent(1, 1); + printf("\n"); + } + /*If MNS is empty, build it based on if there are any source transitions.*/ + result = BuildResult(Dm, Dp, &data, newIndex); + return result; +} + +/******************************************************************************* +This function builds the result structure.*/ +asiph_r BuildResult(matrix *Dm, matrix *Dp, asiph_data* data, int *index) +{ + int i, j, oFlag, iFlag, flag = 0; + int *sourceF; + sourceF = tcalloc(NumberOfColumns(*Dm), sizeof(int)); + + /*Build a set of source transition flags.*/ + + /*If MNS is empty, build a new MNS algorithmically.*/ + if (! NumberOfRows(data->MNS)) + { + /*Find out if there are any source transitions - transitions such that they + have both input and output arcs.*/ + int oFlag, iFlag; + for (j = 0; j < NumberOfColumns(*Dm); j++) + { + iFlag = 0; + oFlag = 0; + for (i - 0; i < NumberOfRows(*Dm); i++) + { + if (GetMatrixEl(Dm, i, j)) oFlag = 1; + if (GetMatrixEl(Dp, i, j)) iFlag = 1; + } + if (iFlag && oFlag) + { + sourceF[j] = 1; + flag = 1; + } + } + /*If there exist source transitions, MNS should be set to a zero-by-m matrix, + m the number of places. Otherwise, it should be set to a 1-m matrix of 1s.*/ + if (flag) + { + if (data->MNS.type) DeallocateMatrix(&data->MNS); + AllocateMatrixType(2, &data->MNS, 0, NumberOfRows(*Dm)); + } + else + { + if (data->MNS.type) DeallocateMatrix(&data->MNS); + AllocateMatrixType(2, &data->MNS, 1, NumberOfRows(*Dm)); + for (i = 0; i < NumberOfRows(*Dm); i++) + { + SetMatrixEl(&data->MNS, 0, i, 1); + } + } + /*Build index*/ + if (index) free(index); + index = tcalloc(NumberOfRows(*Dm), sizeof(int)); + for (i = 0; i < NumberOfRows(*Dm); i++) + { + index[i] = 1; + } + } + /*The result NMS should be a transpose copy of MNS with columns not flagged + in newindex removed. The result MS should be a transpose copy of MNS. Count + how many columns that is.*/ + j = 0; + for (i = 0; i < NumberOfRows(data->MNS); i++) + { + if (index[i]) j++; + } + + asiph_r result; + AllocateMatrixType(2, &result.NMS, NumberOfColumns(data->MNS), j); + AllocateMatrixType(2, &result.MS, NumberOfColumns(data->MNS), NumberOfRows(data->MNS)); + TransposeMatrix(&data->MNS); + CopyMatrix(&data->MNS, &result.MS); + j = 0; + for (i = 0; i < NumberOfColumns(data->MNS); i++) + { + if (index[i]) + { + CopyBlock(NumberOfRows(data->MNS), 1, &data->MNS, 0, i, &result.NMS, 0, j++); + } + } + if (data->MNS.type) DeallocateMatrix(&data->MNS); + if (data->NS.type) DeallocateMatrix(&data->NS); + return result; +} + +/******************************************************************************* +This function displays a real-time (changing) progress percentage. Start by +calling it with a numerator of zero to pring the initial zero-percent text. +Every call for which the division num / denom is nonzero overwrites the previously +displayed percentage - or the last four characters if no percentage has been +displayed yet.*/ +void PrintPercent(int num, int denom) +{ + static int lastPercent = -1; + int percent; + percent = (num * 100) / denom; + if (percent != lastPercent) + { + lastPercent = percent; + if (percent) printf("\b\b\b\b"); + printf("%3d%%", percent); + fflush(stdout); + } +} + +/******************************************************************************* +This function is the innermost processing loop. This adds rows to MT and NT, the +tentative siphons to add to the M and N temporary siphon tables.*/ +int* DoInnerLoop(asiph_data* data, matrix* Dm, matrix *Dp, int *index) +{ + int flag = 1, place, trans, nullPlace, places; + while (flag) + { + /*Allocate the newRow matrix.*/ + AllocateMatrixType(2, &data->newRow, 1, NumberOfRows(*Dm)); + + /*This next section replaces the building of plc and the filling of tst in + the original matlab algorithm. Essently, we want to iterate through all + transitions that have been flagged in curTrans. For each one, we want to + find the index of the counter[i]-th place that has an output arc to the + transition, where i is the transition index. If there is no such place, we + set the nullPlace flag. Otherwise, we set the newRow[index] flag.*/ + nullPlace = 0; + for (trans = 0; trans < NumberOfColumns(*Dm); trans++) + { + if (data->curTrans[trans]) + { + places = 0; + for (place = 0; place < NumberOfRows(*Dm); place++) + { + if (GetMatrixEl(Dm, place, trans)) + { + if (++places == data->counters[trans]) break; + } + } + /*If place is less than the upper limit, then it is the index we want. + Otherwise the index we want does not exist.*/ + if (place < NumberOfRows(*Dm)) + { + SetMatrixEl(&data->newRow, 0, place, 1); + } + else + { + nullPlace = 1; + } + } + } + + /*If the nullPlace flag is set, we found some ith transition without a + counter[i]-th output arc. Free up memory used by the newRow matrix and the + newPlace matrix.*/ + if (nullPlace) + { + DeallocateMatrix(&data->newRow); + DeallocateMatrix(&data->newPlace); + } + /*Otherwise, we can go ahead and add to MT and NT.*/ + else + { + /*Get the newPlaces matrix. There is an element of this for each place, + and it is set to the logic-and of newRow and (logic-not 1st row M). + While we're at it, logic-or newRow with the first row of M.*/ + AllocateMatrixType(2, &data->newPlace, 1, NumberOfRows(*Dm)); + for (place = 0; place < NumberOfRows(*Dm); place++) + { + /*Set newPlace to newRow && ! M(1, :)*/ + SetMatrixEl(&data->newPlace, 0, place, GetMatrixEl(&data->newRow, 0, place) && (! GetMatrixEl(&data->M, 0, place)) ? 1 : 0); + /*Set newRow to newRow | M(1, :)*/ + if (GetMatrixEl(&data->M, 0, place)) + { + SetMatrixEl(&data->newRow, 0, place, 1); + } + } + + /*If check1 returns false, we won't be modifying anything.*/ + if (Check1(&data->MNS, &data->newRow)) + { + /*If Check1 returns true, how we modify depends on if there are any + transitions that meet the GetNewTrans criteria, given newRow as the + place flags. If there are such transitions, run Check2 and modify MT + and NT. If not, modify MNS and newIndex.*/ + if (GetNewTrans(Dm, Dp, &data->newRow, 0)) + { + if (Check2(&data->M, &data->newRow)) + { + InsertRows(&data->MT, &data->newRow, -1, -1); + InsertRows(&data->NT, &data->newPlace, -1, -1); + } + else + { + DeallocateMatrix(&data->newRow); + DeallocateMatrix(&data->newPlace); + } + } + else + { + /*Clear the loop flag. It may be set again later, but it may not be.*/ + flag = 0; + /*Modify MNS and newIndex via insert. The row vector to use is newRow*/ + index = insert(data, &data->newRow, index); + /*Deallocate newPlace.*/ + DeallocateMatrix(&data->newPlace); + } + } + else + { + /*Deallocate the unused matrices.*/ + DeallocateMatrix(&data->newRow); + DeallocateMatrix(&data->newPlace); + } + } + /*Increment the counters and adjust the flag. We are examining only counters + for which curTrans is set.*/ + int i; + for (i = 0; i < NumberOfColumns(*Dm); i++) + { + if (data->curTrans[i]) + { + /*The limit on each counter is the number of input places found earlier.*/ + if (data->counters[i] < data->numInputPlaces[i]) + { + data->counters[i]++; + flag = 1; + break; + } + else + { + data->counters[i] = 0; + flag = 0; + } + } + } + } + return index; +} + +/******************************************************************************* +Check type 2. This runs a check on M and newRow and returns a logical result.*/ +int Check2(matrix* M, matrix* newRow) +{ + /*This check is the same as Check1 except that the second half, examining + rows of M, will return false if there exists any row of M such that it + equals newRow exactly.*/ + int i, j; + /*If all elements of newRow are 1, return false.*/ + for (i = 0; i < NumberOfColumns(*M); i++) + { + if (GetMatrixEl(newRow, 0, i) != 1) break; + } + if (i == NumberOfColumns(*M)) return 0; + + /*Check each row of M. If there exists a row of M that is equal to newRow, + return false.*/ + for (i = 0; i < NumberOfRows(*M); i++) + { + for (j = 0; j < NumberOfColumns(*M); j++) + { + if (GetMatrixEl(M, i, j) != GetMatrixEl(newRow, 0, j)) break; + } + if (j == NumberOfColumns(*M)) + { + return 0; + } + } + return 1; +} + + + +/******************************************************************************* +Check type 1. This runs a check on MNS and newRow and returns a logical result.*/ +int Check1(matrix *MNS, matrix *newRow) +{ + int i, j; + /*If all elements of newRow are 1, return false.*/ + for (i = 0; i < NumberOfColumns(*MNS); i++) + { + if (GetMatrixEl(newRow, 0, i) != 1) break; + } + if (i == NumberOfColumns(*MNS)) return 0; + + /*Check each row of MNS. If there exists a row of MNS such that it has no + element that is true when the corresponding element in newRow is false, return + false.*/ + for (i = 0; i < NumberOfRows(*MNS); i++) + { + for (j = 0; j < NumberOfColumns(*MNS); j++) + { + if (GetMatrixEl(MNS, i, j) && ! GetMatrixEl(newRow, 0, j)) break; + } + if (j == NumberOfColumns(*MNS)) + { + return 0; + } + } + return 1; +} + +/******************************************************************************* +This function sets up all parts of the loop data structure that need to be +initialized for the innermost loop.*/ +void InnerLoopInit(asiph_data* data, matrix *Dm, matrix *Dp) +{ + /*We'll need to get a transition flag array and store it in curTrans in + the loop data structure. Use the algorithm in GetNewTrans, with the first + row of M as the place flags.*/ + GetNewTrans(Dm, Dp, &data->M, data->curTrans); + + /*MT and NT get initialized to matrices with no rows and as many columns as + there are places. They should be set up for fast row ops.*/ + AllocateMatrixType(2, &data->MT, 0, NumberOfRows(*Dm)); + AllocateMatrixType(2, &data->NT, 0, NumberOfRows(*Dm)); + + /*Initialize the counters to 1.*/ + int i; + for (i = 0; i < NumberOfColumns(*Dm); i++) + { + data->counters[i] = 1; + } +} + +/******************************************************************************* +This function sets up all parts of the loop data structure that need to be +initialized for the middle loop. This is M and N.*/ +void MiddleLoopInit(asiph_data* data, asiph_r* result, int siphon) +{ + /*Initialize M and N each to be a copy of the current row of NS, that is, the + current siphon. M and N should be type-2 untransposed for optimized row ops.*/ + AllocateMatrixType(2, &data->M, 1, NumberOfColumns(data->NS)); + AllocateMatrixType(2, &data->N, 1, NumberOfColumns(data->NS)); + CopyBlock(1, NumberOfColumns(data->NS), &data->NS, siphon, 0, &data->M, 0, 0); + CopyBlock(1, NumberOfColumns(data->NS), &data->NS, siphon, 0, &data->N, 0, 0); +} + +/******************************************************************************* +This function sets up all parts of the loop data structure that do not change +ever. This includes two allocations and one allocation and data setup.*/ +void OuterLoopInit(asiph_data* data, matrix *Dm, matrix *Dp, MemoryManager *mem) +{ + /*There is one quantity to be allocated and inialized and two more to be + allocated. All are integer arrays with an element for each transition. + Allocate:*/ + data->numInputPlaces = mcalloc(mem, NumberOfColumns(*Dp), sizeof(int)); + data->curTrans = mcalloc(mem, NumberOfColumns(*Dp), sizeof(int)); + data->counters = mcalloc(mem, NumberOfColumns(*Dp), sizeof(int)); + + /*numInputPlaces has an element for each transition, showing the number of + output arcs that go to that transition.*/ + int i, j, num; + for (j = 0; j < NumberOfColumns(*Dm); j++) + { + for (i = 0; i < NumberOfRows(*Dm); i++) + { + if (GetMatrixEl(Dm, i, j)) data->numInputPlaces[j]++; + } + } +} + +/******************************************************************************* +This function performs a logic operation to develop a set of new transition +flags. It examines places given in the matrix Places and fills in flags in the +integer array Flags. It returns the number of flags set in Flags. +The matrix Places should be a matrix with as many columns as there are places. +The first row will be interpreted as a flag array. +The array Flags should have an element for each transition. If Flags is a null +pointer it is ignored and the function optimizes by returning as soon as any +transition meeting the criteria is encountered.*/ +int GetNewTrans(matrix *Dm, matrix *Dp, matrix *Places, int *Flags) +{ + /*We want to set the flag for each transition such that it has at least one + input arc going to one of the flagged places and no output arcs coming from any + of the flagged places.*/ + int transition, place, iFlag, oFlag, flagged; + flagged = 0; + for (transition = 0; transition < NumberOfColumns(*Dm); transition++) + { + iFlag = 0; + oFlag = 0; + for (place = 0; place < NumberOfRows(*Dm); place++) + { + /*Examine only if the current place is flagged.*/ + if (GetMatrixEl(Places, 0, place)) + { + /*If there is an input arc, set the iFlag.*/ + if (GetMatrixEl(Dp, place, transition)) + { + iFlag = 1; + } + /*If there is an output arc, set the oFlag and break.*/ + if (GetMatrixEl(Dm, place, transition)) + { + oFlag = 1; + break; + } + } + } + /*Does the transition meet the criteria?*/ + if (iFlag && ! oFlag) + { + /*If Flags is present, set it and increment the counter. If not, we are + in fast mode. Merely return 1 now.*/ + if (Flags) + { + Flags[transition] = 1; + flagged++; + } + else + { + return 1; + } + } + else if (Flags) + { + Flags[transition] = 0; + } + } + return flagged; +} + +/******************************************************************************* +This function does initial building on MNS and NS. It also builds the initial +newIndex vector and returns it to the main function for later use.*/ +int *DataInit(matrix *Dm, matrix *Dp, matrix *PS, matrix *sx, asiph_data* data) +{ + /*newIndex defaults to an array of zeros with one element for each column of + PS. If PS is empty (null pointer), newIndex becomes a null pointer as well.*/ + int *newIndex = PS ? tcalloc(NumberOfColumns(*PS), sizeof(int)) : 0; + + /*We are going to iterate through the columns of sx. Each column is an active + siphon. For each siphon, we determine if there are any transitions such that + they have at least one input arc to a place in the siphon but no output arcs + from any places in the siphon. If there are, we modify NS (in result). If not, + we modify MNS (in result) and newIndex.*/ + int siphon, place, transition, iFlag, oFlag; + for (siphon = 0; siphon < NumberOfColumns(*sx); siphon++) + { + /*We need a row vector containing a copy of the current siphon column. + Build it.*/ + matrix rowSX; + AllocateMatrixType(2, &rowSX, 1, NumberOfRows(*sx)); + for (place = 0; place < NumberOfRows(*sx); place++) + { + SetMatrixEl(&rowSX, 0, place, GetMatrixEl(sx, place, siphon)); + } + + /*Find out whether the transitions meet the criteria via GetNewTrans. It will + return 1 if it finds any transitions that meet the criteria.*/ + if (GetNewTrans(Dm, Dp, &rowSX, 0)) + { + /*We are going to add a row to NS consisting of the current column of sx.*/ + /*Build a matrix (type-2 untransposed for optimization) and do an + insertion. This column insertion will be optimized)*/ + InsertRows(&data->NS, &rowSX, -1, -1); + } + /*If no siphons met the criteria, use ins to modify MNS and newIndex.*/ + else + { + newIndex = insert(data, &rowSX, newIndex); + } + } + return newIndex; +} + +/******************************************************************************* +This function modifies MNS and newindex based on a given row vector.*/ +int* insert(asiph_data* data, matrix* vector, int* index) +{ + /*We need an array of flags, one for each row of the MNS vector. The flags + will be set if that row should be removed.*/ + int *removeMNSRow = tcalloc(NumberOfRows(data->MNS), sizeof(int)); + int removeCount = 0; + /*Iterate through each row of MNS*/ + int i, j, flag = 1; + for (i = 0; i < NumberOfRows(data->MNS); i++) + { + /*Take the difference MNS - vector. Fill sumDeltas with the sum of the + differences at each element. Set the minusDeltas flag if any of the differences + are negative.*/ + int sumDeltas = 0, minusDeltas = 0, j, delta; + for (j = 0; j < NumberOfColumns(data->MNS); j++) + { + delta = GetMatrixEl(&data->MNS, i, j) - GetMatrixEl(vector, 0, j); + if (delta < 0) minusDeltas = 1; + sumDeltas += delta; + } + /*If any of the differences were negative, do nothing.*/ + if (! minusDeltas) + { + /*If the flag is still set...*/ + if (flag) + { + /*If the sum of the deltas is nonzero, set the current row of MNS to vector + and set the index flag.*/ + if (sumDeltas) + { + CopyBlock(1, NumberOfColumns(data->MNS), vector, 0, 0, &data->MNS, i, 0); + index[i] = 1; + } + /*Clear the flag*/ + flag = 0; + } + /*If the flag isn't still set, mark the current MNS row for removal and + clear the index flag.*/ + else + { + removeCount++; + removeMNSRow[i] = 1; + index[i] = 0; + } + } + } + /*Initialize space for the new index. We'll be removing all the elements + flagged in removeMNSRow. We'll be adding an element iff flag is still set.*/ + int* newIndex = tcalloc(NumberOfRows(data->MNS) - removeCount + flag, sizeof(int)); + + /*Fill in the new index and remove rows from MNS.*/ + j = 0; + for (i = 0; i < NumberOfRows(data->MNS); i++) + { + if (removeMNSRow[i]) + { + RemoveRows(&data->MNS, i, 1, -1); + } + else + { + newIndex[j++] = index[i]; + } + } + /*Fill in the last element of index and the last row of MNS if necessary.*/ + if (flag) + { + InsertRows(&data->MNS, vector, -1, -1); + newIndex[NumberOfRows(data->MNS) - 1] = 1; + } + else + { + /*If vector's memory was not merged into MNS in the row insertion, deallocate + vector here for consistency's sake.*/ + DeallocateMatrix(vector); + } + /*Deallocate the flag array.*/ + free(removeMNSRow); + /*Free the old index.*/ + free(index); + /*Return the new index.*/ + return newIndex; +} + +/******************************************************************************* +This function finds the precomputed set of active siphons that are present in +the active subnet. It also performs some initialization of result.*/ +matrix SXInit(matrix *Dm, matrix *Dp, matrix *Dma, matrix* Dpa, matrix *PS, int **list, int* listCount, asiph_data* data) +{ + matrix sx; + int i, j, k, newCount; + int *newList; + MemoryManager memory = CreateMemoryManager(2, 2, 0, 0); + asiph_r recursive; + /*We need to build a list of the indices of places that are in the active + subnet (have a non-null row in Dma/Dpa). Count them.*/ + newCount = NumberOfRows(*Dma); + for (i = 0; i < NumberOfRows(*Dma); i++) + { + for (j = 0; j < NumberOfColumns(*Dma); j++) + { + if (GetMatrixEl(Dma, i, j) || GetMatrixEl(Dpa, i, j)) break; + } + /*Was the row null?*/ + if (j == NumberOfColumns(*Dma)) + { + newCount--; + } + } + /*If the entire net is inactive, then asiph should return empty matrices. + To signify this, return an empty SXInit matrix.*/ + if (! newCount) + { + memset(&sx, 0, sizeof(matrix)); + return sx; + } + /*Otherwise, build the actual list of non-null Dma/Dpa row indices.*/ + k = 0; + newList = mcalloc(&memory, newCount, sizeof(int)); + for (i = 0; i < NumberOfRows(*Dma); i++) + { + for (j = 0; j < NumberOfColumns(*Dma); j++) + { + if (GetMatrixEl(Dma, i, j) || GetMatrixEl(Dpa, i, j)) break; + } + /*Was the row non-null?*/ + if (j < NumberOfColumns(*Dma)) + { + newList[k++] = i; + } + } + + /*If the entire net is active, then sx is simply a modified identity.*/ + if (MatrixEqualMatrix(Dm, Dma) && MatrixEqualMatrix(Dp, Dpa)) + { + /*There will be a column of sx for each place the index of which is present + in the list. Each of these will have exactly one 1, the row number of which + is the same as the original place number.*/ + AllocateMatrixType(2, &sx, NumberOfRows(*Dm), *listCount); + for (i = 0; i < *listCount; i++) + { + SetMatrixEl(&sx, (*list)[i], i, 1); + } + } + /*Otherwise, we use the new list and build a new known PS and call asiph + recursively.*/ + else + { + matrix NewPS; + if (PS) + { + /*NewPS should be a copy of PS, with rows corresponding to inactive places + (null rows in Dma/Dpa) zeroed and with duplicate columns removed. + Allocate as a type-2 transpose to optimize for rapid column removal (see + RemoveColumns).*/ + MAllocateMatrixType(&memory, 2, &NewPS, NumberOfColumns(*PS), NumberOfRows(*PS)); + TransposeMatrix(&NewPS); + CopyMatrix(PS, &NewPS); + /*Zero rows corresponding to zero rows of both Dma and Dpa.*/ + for (i = 0; i < NumberOfRows(*Dma); i++) + { + for (j = 0; j < NumberOfColumns(*Dma); j++) + { + if (GetMatrixEl(Dma, i, j) || GetMatrixEl(Dpa, i, j)) + { + break; + } + } + /*Was the row zero?*/ + if (j == NumberOfColumns(*Dma)) + { + /*If so, zero the corresponding row of NewPS.*/ + MakeZeroRow(&NewPS, i); + } + } + /*Remove duplicate columns*/ + for (i = 0; i < NumberOfColumns(NewPS) - 1; i++) + { + for (j = i + 1; j < NumberOfColumns(NewPS); j++) + { + /*Check the columns i and j.?*/ + for (k = 0; k < NumberOfRows(NewPS); k++) + { + if (GetMatrixEl(&NewPS, k, i) != GetMatrixEl(&NewPS, k, j)) + { + break; + } + } + /*Are they identical?*/ + if (k == NumberOfRows(NewPS)) + { + /*If so, remove the jth column.*/ + RemoveColumns(&NewPS, j, 1, -1); + } + } + } + } + + /*Call asiph recursively on Dma and Dpa.*/ + recursive = asiph(Dma, Dpa, newList, newCount, PS ? &NewPS : 0, 0, 0); + sx = recursive.MS; + + /*Free memory if necessary.*/ + if (recursive.NMS.type) DeallocateMatrix(&recursive.NMS); + } + /*Setup the data matrices appropriately. NMS should be the transpose copy + of PS. If PS is empty, then setup NMS with zero rows and the same number + of columns as there are places so that row additions will work. + NS should be an empty matrix setup with zero rows and the same number of + columns as there are places. + Both matrices should be type-2 untransposed to optimize for row ops.*/ + if (PS) + { + AllocateMatrixType(2, &data->MNS, NumberOfColumns(*PS), NumberOfRows(*PS)); + TransposeMatrix(PS); + CopyMatrix(PS, &data->MNS); + TransposeMatrix(PS); + } + else + { + AllocateMatrixType(2, &data->MNS, 0, NumberOfRows(*Dm)); + } + AllocateMatrixType(2, &data->NS, 0, NumberOfRows(*Dm)); + return sx; +} + +/******************************************************************************* +This function checks the parameters to verify that the right ones are present, +sizes match, indices are within range, and so forth.*/ +int CheckParams(matrix *Dm, matrix *Dp, int **list, int *listCount, matrix *PS, matrix **Dma, matrix **Dpa, MemoryManager *mem) +{ + int i, j; + /*Dm and Dp are required and must be the same size.*/ + if (! (Dm && Dp)) + { + merror(0, "ASIPH: A required parameter was a null pointer"); + return 0; + } + if (NumberOfRows(*Dm) != NumberOfRows(*Dp) || NumberOfColumns(*Dm) != NumberOfColumns(*Dp)) + { + merror(0, "ASIPH: The input and output matrices are not the same size"); + return 0; + } + + /*List is not required. If not present, it defaults to including the + indices of each place. It is checked to be sure it includes no duplicate or + spurious indices.*/ + if (! *list) *listCount = 0; + if (! *listCount) + { + *listCount = NumberOfRows(*Dm); + *list = mcalloc(mem, *listCount, sizeof(int)); + for (i = 1; i < *listCount; i++) + { + (*list)[i] = i; + } + } + else + { + for (i = 0; i < *listCount; i++) + { + /*Make sure no entries are out-of-range.*/ + if ((*list)[i] < 0 || (*list)[i] >= NumberOfRows(*Dm)) + { + FreeMemory(mem); + merror(0, "ASIPH: One of the indices in the place list is out of range"); + return 0; + } + /*Make sure no entries are duplicate.*/ + for (j = i + 1; j < *listCount; j++) + { + if ((*list)[i] == (*list)[j]) + { + FreeMemory(mem); + merror(0, "ASIPH: The place list contains duplicate entries"); + return 0; + } + } + } + } + /*PS is not required but if present must have the same number of rows as + Dm/Dp.*/ + if (PS) + { + if (NumberOfRows(*PS) != NumberOfRows(*Dm)) + { + FreeMemory(mem); + merror(0, "ASIPH: PS does not have the same number of rows as the Petri net matrices"); + return 0; + } + } + /*Dma and Dpa are not required. If present they must be the same size as Dp & + Dp. If not present they will be found via call to actn.*/ + if (*Dma && *Dpa) + { + if (NumberOfRows(**Dma) != NumberOfRows(**Dpa) || NumberOfColumns(**Dma) != NumberOfColumns(**Dpa)) + { + FreeMemory(mem); + merror(0, "ASIPH: Dma and/or Dpa is not the same size as Dm and Dp"); + return 0; + } + } + else + { + actn_r result; + result = actn(Dm, Dp, 0, 0, 0, 0, 0, 0); + ManageMatrix(mem, &result.Dma); + ManageMatrix(mem, &result.Dpa); + if (result.Dmra.type) DeallocateMatrix(&result.Dmra); + if (result.Dpra.type) DeallocateMatrix(&result.Dpra); + + *Dma = mmalloc(mem, sizeof(matrix)); + **Dma = result.Dma; + *Dpa = mmalloc(mem, sizeof(matrix)); + **Dpa = result.Dpa; + if (result.TA) free(result.TA); + } + return 1; +} Modified: spnbox/deallocation.c =================================================================== --- spnbox/deallocation.c 2009-07-17 16:40:11 UTC (rev 199) +++ spnbox/deallocation.c 2009-07-22 00:37:02 UTC (rev 200) @@ -150,3 +150,9 @@ { FreeMemorySafe(data->flag); } + +void DeallocateAsiph(asiph_r *data) +{ + FreeMatrixSafe(&data->MS); + FreeMatrixSafe(&data->NMS); +} Modified: spnbox/spnbox.h =================================================================== --- spnbox/spnbox.h 2009-07-17 16:40:11 UTC (rev 199) +++ spnbox/spnbox.h 2009-07-22 00:37:02 UTC (rev 200) @@ -162,10 +162,24 @@ typedef struct issiph_r { + /*An array of flags, one for each proposed siphon, set for each one that was + a siphon.*/ int* flag; + /*This flag will be set if any of the proposed siphons were NOT siphons.*/ int flx; } issiph_r; +typedef struct asiph_r +{ + /*The modified list of known active siphons - those that were given and + those that were added by the asiph procedure. Given as a matrix with a row + for each place and a column for each siphon. An element will be nonzero if + the corresponding place is a part of the corresponding siphon.*/ + matrix MS; + /*The list of active siphons added by the asiph procedure. Same format as MS.*/ + matrix NMS; +} asiph_r; + /*Functions to free return structures. Implemented in deallocation.c*/ void DeallocateSupervis(supervis_r *data); void DeallocateIpslv(ipslv_r *data); @@ -181,6 +195,7 @@ void DeallocateActn(actn_r *data); void DeallocateTactn(tactn_r *data); void DeallocateIssiph(issiph_r *data); +void DeallocateAsiph(asiph_r *data); /*Constants returned in by functions to indicate the nature of the result.*/ #define HOW_ERROR "error" @@ -201,6 +216,7 @@ #define VRB_REDUCE 3 #define VRB_DP 2 #define VRB_ILPADM 2 +#define VRB_ASIPH 3 #define VRB_MAX 10 msplit_r msplit(matrix* Dm, matrix* Dp, int* mask, matrix* M, matrix* L0, matrix* L, int* ipl, int ipCount, int* dpl, int dpCount, int** TD, int* TDCount); @@ -780,4 +796,50 @@ Converted to C by Marian V. Iordache and Stephen Camp, ste...@le.... */ +asiph_r asiph(matrix *Dm, matrix *Dp, int* list, int listCount, matrix *PS, matrix *Dma, matrix *Dpa); +/* +ASIPH - find minimal active siphons: direct implementation + +[MS, NMS] = asiph(D) + +[MS, NMS] = asiph(D^-,D^+,list,PAS, Dma, Dpa) + +[MS, NMS] = asiph(D^-,D^+,list,PAS, Dma, Dpa, verb) + +'list' is an optional argument that should specify a subset of +{1, ..., m}, where m is the number of rows of the incidence matrix. +When 'list is used, only act. siphons that include one or more of the +places from 'list' are returned. This feature allows the program to +run faster. However note that in this case the result is the set of +smallest act. siphons that include the places from the list; this includes +the set of minimal act. siphons that contain places from list, but it may +include other act. siphons as well. Therefore the 3rd argument is useful +when it is known (from theoretical considerations) that all returned +act. siphons are minimal. This is the case in SDP. If list = [], the +program sets it to the default value list = 1:m. + +The columns of PAS are already known active siphons. Dma and Dpa are +the incidence matrices of the active subnet. + +When Dma and Dpa are omitted, the maximal active subnet is assumed. + +MS is the updated PAS, and NMS the new minimal active siphons. + +verb (default is 1) stands for verbosity. If verb = 1, the program will +display some information about its progress. + +See also MSIPH, SIPH2, MINSIPH + +Written for Matlab by Marian V. Iordache, mar...@le... +Converted to C by Marian V. Iordache and Stephen Camp, ste...@le... + +lst feature is not yet fully implemented! (the case when a source place +appears in the list has not been considered). + +C Usage: +Parameters are the same and have the same meanings as in Matlab, except that +PAS in the Matlab version is PS in the C version. list is passed as a pointer +to an integer array containing the indices in the list followed by a single +integer, listCount, that should be set to the length of the list. +*/ #endif Modified: spnbox/tests/Makefile =================================================================== --- spnbox/tests/Makefile 2009-07-17 16:40:11 UTC (rev 199) +++ spnbox/tests/Makefile 2009-07-22 00:37:02 UTC (rev 200) @@ -17,8 +17,9 @@ ISSIPH=issiph.o MSPLIT=msplit.o PN2ACPN=pn2acpn.o -SUPERVIS=supervis.o $(EXTENDEDMATRIX.O) +SUPERVIS=supervis.o $(EXTENDEDMATRIX) ACTN=actn.o $(NLTRANS) +ASIPH=asiph.o $(ACTN) $(EXTENDEDMATRIX) ILPADM=ilpadm.o $(IPSOLVE) LINENF=linenf.o $(ILPADM) NLTRANS=nltrans.o $(IPSOLVE) @@ -51,6 +52,8 @@ $(COMPILER) -o supervis.exe test-supervis.o $(COMMON) $(EXTENDEDMATRIX) $(SUPERVIS) actn: test-actn.o $(COMMON) $(ACTN) $(COMPILER) -o actn.exe test-actn.o $(COMMON) $(ACTN) +asiph: test-asiph.o $(COMMON) $(ASIPH) + $(COMPILER) -o asiph.exe test-asiph.o $(COMMON) $(ASIPH) ilpadm: test-ilpadm.o $(COMMON) $(ILPADM) $(COMPILER) -o ilpadm.exe test-ilpadm.o $(COMMON) $(ILPADM) linenf: test-linenf.o $(COMMON) $(LINENF) @@ -71,6 +74,8 @@ #Rules for making the general object files. actn.o: ../actn.c ../spnbox.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../matrixmath.h ../MemoryManager.h $(COMPILER) -c ../actn.c +asiph.o: ../asiph.c ../spnbox.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../extendedmatrix.h ../MemoryManager.h + $(COMPILER) -c ../asiph.c chkcons.o: ../spnbox.h ../../pnheaders/matrix.h ../../pnheaders/pns.h ../chkcons.c $(COMPILER) -c ../chkcons.c deallocation.o: ../deallocation.c ../spnbox.h @@ -107,7 +112,7 @@ $(COMPILER) -c ../pn2eacpn.c pns.o: ../../pnheaders/pns.c ../../pnheaders/pns.h ../../pnheaders/general.h ../../pnheaders/matrix.h $(COMPILER) -c ../../pnheaders/pns.c -reduce.o: ../spnbox.h ../../pnheaders/matrix.h ../reduce.c +reduce.o: ../spnbox.h ../extendedmatrix.h ../../pnheaders/matrix.h ../reduce.c $(COMPILER) -c ../reduce.c supervis.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/ ../../pnheaders/matrix.h ../supervis.c ../extendedmatrix.h $(COMPILER) -c ../supervis.c @@ -121,6 +126,8 @@ #Rules for making the test executable object files. test-actn.o: test-actn.c $(COMMONHEADER) $(COMPILER) -c test-actn.c +test-asiph.o: test-asiph.c $(COMMONHEADER) + $(COMPILER) -c test-asiph.c test-extendedmatrix.o: test-extendedmatrix.c $(COMMONHEADER) $(COMPILER) -c test-extendedmatrix.c test-ilpadm.o: test-ilpadm.c $(COMMONHEADER) Added: spnbox/tests/test-asiph.c =================================================================== --- spnbox/tests/test-asiph.c (rev 0) +++ spnbox/tests/test-asiph.c 2009-07-22 00:37:02 UTC (rev 200) @@ -0,0 +1,39 @@ +#include "test.h" + +int main(int argc, char* argv[]) +{ + char iDesc[] = "matrix D, matrix Dm, matrix Dp, arrayi list, matrix PS, matrix Da, matrix Dma, matrix Dpa"; + char oDesc[] = "matrix MS, matrix NMS"; + matrix D, Dm, Dp, PS, Da, Dma, Dpa; + int listCount; + int *list, *iSet; + int oSet[] = {1, 1}; + + FILE* input; + + if (! (input = ParseCmdLine(argc, argv))) return 0; + + setverbose(VRB_MAX); + MemoryManager mem = CreateMemoryManager(10, 10, 0, 0); + while (ParseStructure(input, iDesc, &iSet, &mem, &D, &Dm, &Dp, &list, &listCount, &PS, &Da, &Dma, &Dpa)) + { + DisplayStructure(iDesc, iSet, &D, &Dm, &Dp, list, listCount, &PS, &Da, &Dma, &Dpa); + FillDmDp(iSet, &D, &Dm, &Dp, &mem); + FillDmDp(iSet + 5, &Da, &Dma, &Dpa, &mem); + + asiph_r result = asiph(iSet[1] ? &Dm : 0, iSet[2] ? &Dp : 0, iSet[3] ? list : 0, iSet[3] ? listCount : 0, iSet[4] ? &PS : 0, iSet[6] ? &Dma : 0, iSet[7] ? &Dpa : 0); + printf("Solution:\n"); + + DisplayStructure(oDesc, oSet, &result.MS, &result.NMS); + + DeallocateAsiph(&result); + + FreeMemory(&mem); + mem = CreateMemoryManager(10, 10, 0, 0); + printf("-------------------------------------------------------------------------------\n"); + } + FreeMemory(&mem); + + if (input != stdin) fclose(input); + return 0; +} Added: spnbox/tests/test-asiph.txt =================================================================== --- spnbox/tests/test-asiph.txt (rev 0) +++ spnbox/tests/test-asiph.txt 2009-07-22 00:37:02 UTC (rev 200) @@ -0,0 +1,142 @@ +rem "matrix D, matrix Dm, matrix Dp, arrayi list, matrix PS, matrix Da, matrix Dma, matrix Dpa" + +echo Problem 1. +Dm 4 3 +0 1 0 +1 0 0 +0 0 1 +0 0 1 + +Dp 4 3 +1 0 0 +0 0 1 +0 1 0 +0 0 0 + +done + +echo Problem 2. +Dm 5 4 +0 1 0 0 +1 0 0 0 +0 0 1 0 +0 0 0 1 +0 0 0 1 + +Dp 5 4 +1 0 0 0 +0 0 1 0 +0 1 0 1 +0 0 0 0 +0 0 0 0 +done + +echo Problem 3 +Dm 5 4 +1 0 0 0 +0 1 0 0 +0 0 1 0 +0 0 0 1 +0 0 0 0 +Dp 5 4 +0 0 0 0 +1 0 0 0 +0 1 0 0 +0 0 1 0 +0 0 0 1 +done + +echo Problem 4 +echo Answer should be: +echo 1 0 0 0 +echo 0 1 1 0 +echo 0 0 0 1 +echo 1 1 0 0 +echo 0 0 1 1 +echo 1 1 1 1 +Dm 6 5 +1 0 0 0 0 +1 1 0 0 0 +0 1 0 0 0 +0 0 0 1 0 +0 0 0 1 0 +0 0 1 0 1 +Dp 6 5 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 1 0 0 +0 1 0 0 1 +0 0 0 2 0 +done + +echo Problem 5 +D 6 7 +-1 0 0 0 0 0 0 + 1 -1 -1 0 0 0 0 + 0 0 1 -1 1 0 0 +-1 1 0 0 0 -1 1 + 0 0 0 1 -1 0 0 + 0 0 0 0 0 1 -1 +done + +echo Problem 6 +echo This problem merely adds a list of already-known active siphons. +echo It uses the Petri net of problem 4 and gives the first two +echo siphons as already known. +echo Answer should be: +echo 1 0 0 0 +echo 0 1 1 0 +echo 0 0 0 1 +echo 1 1 0 0 +echo 0 0 1 1 +echo 1 1 1 1 +Dm 6 5 +1 0 0 0 0 +1 1 0 0 0 +0 1 0 0 0 +0 0 0 1 0 +0 0 0 1 0 +0 0 1 0 1 +Dp 6 5 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 1 0 0 +0 1 0 0 1 +0 0 0 2 0 +PS 6 2 +1 0 +0 1 +0 0 +1 1 +0 0 +1 1 +done + +echo Problem 7 +echo This problem is the same as Problem 4 but provides Dma/Dpa +echo to begin with, as a test of the handling of that parameter. +Da 6 5 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 1 -1 0 +0 0 0 -1 1 +0 0 -1 2 -1 +Dm 6 5 +1 0 0 0 0 +1 1 0 0 0 +0 1 0 0 0 +0 0 0 1 0 +0 0 0 1 0 +0 0 1 0 1 +Dp 6 5 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 1 0 0 +0 1 0 0 1 +0 0 0 2 0 +done +quit Modified: spnbox/tests/test.c =================================================================== --- spnbox/tests/test.c 2009-07-17 16:40:11 UTC (rev 199) +++ spnbox/tests/test.c 2009-07-22 00:37:02 UTC (rev 200) @@ -1,11 +1,9 @@ #include "test.h" -int verbose; +int verbose = 0; int is_verbose() { - /*We want maximum verbosity. reduce uses chkcons, so return whichever - verbosity threshold is higher.*/ return verbose; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-17 16:40:13
|
Revision: 199 http://pntool.svn.sourceforge.net/pntool/?rev=199&view=rev Author: StephenCamp Date: 2009-07-17 16:40:11 +0000 (Fri, 17 Jul 2009) Log Message: ----------- Found an apparent bug in matrix.c, line 371. CopyMatrix was improperly handling transposed matrices - it was examining nr and nc in the matrix without regard to transpose state. Modified Paths: -------------- pnheaders/matrix.c Modified: pnheaders/matrix.c =================================================================== --- pnheaders/matrix.c 2009-07-15 13:21:23 UTC (rev 198) +++ pnheaders/matrix.c 2009-07-17 16:40:11 UTC (rev 199) @@ -368,7 +368,7 @@ void CopyMatrix(const matrix* src, matrix* dst) { - CopyBlock(src->nr, src->nc, src, 0, 0, dst, 0, 0); + CopyBlock(NumberOfRows(*src), NumberOfColumns(*src), src, 0, 0, dst, 0, 0); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-15 13:21:26
|
Revision: 198 http://pntool.svn.sourceforge.net/pntool/?rev=198&view=rev Author: StephenCamp Date: 2009-07-15 13:21:23 +0000 (Wed, 15 Jul 2009) Log Message: ----------- Forgot to check the speed-testing options in the test routines earlier. Checked and debugged now. Modified Paths: -------------- spnbox/tests/test-extendedmatrix.c spnbox/tests/test-extendedmatrix.txt Modified: spnbox/tests/test-extendedmatrix.c =================================================================== --- spnbox/tests/test-extendedmatrix.c 2009-07-14 21:32:17 UTC (rev 197) +++ spnbox/tests/test-extendedmatrix.c 2009-07-15 13:21:23 UTC (rev 198) @@ -50,7 +50,7 @@ mem = CreateMemoryManager(5, 2, 0, 0); SetDefaults(optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size, speedtest); - while (ParseStructure(input, Desc, &Filled, &mem, optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size)) + while (ParseStructure(input, Desc, &Filled, &mem, optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size, speedtest)) { Optimized = ! strcmp(optimization, "yes"); if (Optimized) Mode = -1; @@ -154,7 +154,7 @@ } double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); ShowMatrix(outer, "Sample Matrix After"); - printf("Time: %.2f ms", time / 1000.0); + printf("Time: %.2f ms\n", time * 1000.0); DeallocateMatrices(Reps, outer); } @@ -174,7 +174,7 @@ } double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); ShowMatrix(outer, "Sample Matrix After"); - printf("Time: %.2f ms", time / 1000.0); + printf("Time: %.2f ms\n", time * 1000.0); DeallocateMatrices(Reps, outer); } @@ -260,7 +260,7 @@ } double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); ShowMatrix(m, "Sample Matrix After"); - printf("Time: %.2f ms", time / 1000.0); + printf("Time: %.2f ms\n", time * 1000.0); DeallocateMatrices(Reps, m); } @@ -280,7 +280,7 @@ } double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); ShowMatrix(m, "Sample Matrix After"); - printf("Time: %.2f ms", time / 1000.0); + printf("Time: %.2f ms\n", time * 1000.0); DeallocateMatrices(Reps, m); } @@ -352,7 +352,7 @@ } double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); ShowMatrix(m, "Sample Matrix After"); - printf("Time: %.2f ms", time / 1000.0); + printf("Time: %.2f ms\n", time * 1000.0); DeallocateMatrices(Reps, m); } @@ -372,7 +372,7 @@ } double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); ShowMatrix(m, "Sample Matrix After"); - printf("Time: %.2f ms", time / 1000.0); + printf("Time: %.2f ms\n", time * 1000.0); DeallocateMatrices(Reps, m); } @@ -453,7 +453,7 @@ PrintPercent(0, 1); for (i = 0; i < reps; i++) { - AllocateMatrixType(2, m + i, rows, cols); + AllocateMatrixType(2, m + i, Transpose ? cols : rows, Transpose ? rows : cols); if (Transpose) TransposeMatrix((m) + i); PrintPercent(i + 1, reps); } Modified: spnbox/tests/test-extendedmatrix.txt =================================================================== --- spnbox/tests/test-extendedmatrix.txt 2009-07-14 21:32:17 UTC (rev 197) +++ spnbox/tests/test-extendedmatrix.txt 2009-07-15 13:21:23 UTC (rev 198) @@ -137,4 +137,64 @@ columns 1 optimization yes done + +echo Problem 13. Null row insertion, unoptimized speedtest. +operation InsertNullRows +size 20 +repetitions 20000 +speedtest yes +optimization no +row 1 +rows 2 +done + +echo Problem 14. Null row insertion, optimized speedtest. +operation InsertNullRows +size 20 +repetitions 20000 +speedtest yes +optimization yes +row 1 +rows 2 +done + +echo Problem 15. Column insertion, unoptimized speedtest. +operation InsertColumns +size 20 +repetitions 20000 +speedtest yes +optimization no +column 1 +columns 2 +done + +echo Problem 16. Column insertion, optimized speedtest. +operation InsertColumns +size 20 +repetitions 20000 +speedtest yes +optimization yes +column 1 +columns 2 +done + +echo Problem 17. Row removal, unoptimized speedtest. +operation RemoveRows +size 20 +repetitions 20000 +speedtest yes +optimization no +row 1 +rows 2 +done + +echo Problem 18. Row removal, optimized speedtest. +operation RemoveRows +size 20 +repetitions 20000 +speedtest yes +optimization yes +row 1 +rows 2 +done quit This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-14 21:32:21
|
Revision: 197 http://pntool.svn.sourceforge.net/pntool/?rev=197&view=rev Author: StephenCamp Date: 2009-07-14 21:32:17 +0000 (Tue, 14 Jul 2009) Log Message: ----------- Added notes to spnbox.h function comments about the differences between C and Matlab usage. Added a "help" feature to the test routines, allowing a user to get some information from the test programs themselves about how they should be used. (Had to modify virtually all test files very slightly to get this done.) Modified Paths: -------------- spnbox/spnbox.h spnbox/tests/StructuredIO.c spnbox/tests/StructuredIO.h spnbox/tests/test-actn.c spnbox/tests/test-extendedmatrix.c spnbox/tests/test-ilpadm.c spnbox/tests/test-ipsolve.c spnbox/tests/test-isadm.c spnbox/tests/test-issiph.c spnbox/tests/test-linenf.c spnbox/tests/test-matrixmath.c spnbox/tests/test-msplit.c spnbox/tests/test-nltrans.c spnbox/tests/test-pn2acpn.c spnbox/tests/test-pn2eacpn.c spnbox/tests/test-reduce.c spnbox/tests/test-supervis.c spnbox/tests/test-tactn.c spnbox/tests/test.c spnbox/tests/test.h Modified: spnbox/spnbox.h =================================================================== --- spnbox/spnbox.h 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/spnbox.h 2009-07-14 21:32:17 UTC (rev 197) @@ -6,8 +6,8 @@ #include "../third-party/lp_solve_5.5/lpkit.h" typedef struct supervis_r { /* result of supervis */ - matrix Dfm; - matrix Dfp; + matrix Dfm; //The supervised net output matrix + matrix Dfp; //The supervised net input matrix } supervis_r; typedef struct ipslv_r { @@ -17,17 +17,19 @@ } ipslv_r; typedef struct ipsolve_r { /*Result of ipsolve*/ - double* res; - char* mhow; + double* res; //A pointer to an array of doubles containing the solution. + char* mhow; //A pointer to a statically-defined result message. DO NOT + //DEALLOCATE! } ipsolve_r; typedef struct ilpadm_r {/*Result of ilpadm*/ - matrix La; - int* ba; - matrix R1; - matrix R2; - char* how; - char** dhow; + matrix La; //The new constraint matrix. + int* ba; //The new constraint vector, given as a pointer to an integer array. + matrix R1; //The transform matrix R1. + matrix R2; //The transform matrix R2. + char* how; //Overall result message. Statically defined (do not deallocate). + char** dhow; //Array of result messages, one for each constraint. The array + //may be deallocated, but the individual messages should not be. } ilpadm_r; typedef struct linenf_r @@ -67,58 +69,90 @@ typedef struct nltrans_r { - int* dtr; - int dtrCount; + int* dtr; //The list of unraisable transitions given as a pointer to an array + int dtrCount; //The number of elements in the dtr array } nltrans_r; typedef struct pn2acpn_r { - matrix Df; - matrix Dmf; - matrix Dpf; - matrix MXF; + //The final Petri net matrices + matrix Df; + matrix Dmf; + matrix Dpf; + //Modified constraint matrices + matrix MXF; matrix L0F; matrix LF; + //The new independent place list, given as a pointer to an array of integers int *iplf; + //The number of independent places (length of the iplf array) int iplfCount; } pn2acpn_r; typedef struct pn2eacpn_r { + //New Petri net matrices matrix Df; matrix Dmf; matrix Dpf; + //New constraint matrices matrix MXF; matrix L0F; matrix LF; + //New independent place list, given as a pointer to an array of integers. int *iplf; + //Length of the independent place list. int iplfCount; + /*New list of transitions that are unraisable when a given transition is dead. + This is a pointer to an array of integer arrays. There is an element for each + transition. Each array lists the transitions that cannot be raised if the + transition that array corresponds to is dead.*/ int **TD; + /*The number of elements in each of the arrays in the TD array of arrays. + This is a pointer to an array of integers, one for each transition, that lists + the number of elements in the corresponding array in TD.*/ int *TDCount; } pn2eacpn_r; typedef struct chkcons_r { + /*The solution of the ipsolve problem that is done internally.*/ double* res; + /*The number of elements in the solution array.*/ int resCount; } chkcons_r; typedef struct reduce_r { + /*The new constraint matrix*/ matrix Lf; + /*The new constraint vector (an array of integers)*/ int* Bf; + /*An array of integers, each one of which is the index of an original transition + that was kept. + Has as many elements as there are rows in Lf.*/ int* indf; + /*An integer giving a status message. See "reduce" for meaning.*/ int how; } reduce_r; typedef struct actn_r { + /*The input and output matrices of the active subnet, given as a copy of the + original subnet with dead transitions and/or places overwritten with zeroes.*/ matrix Dma; matrix Dpa; + /*The input and output matrices of the active subnet, given as those rows from + Dma and Dpa that were not overwritten with zeroes.*/ matrix Dmra; matrix Dpra; + /*The list of active transitions. This is a pointer to an array of integers, + each one of which is the index of a transition that made it into the active + subnet.*/ int* TA; + /*The number of active transitions, i.e. length of the TA list.*/ int TACount; + /*This flag will be meaninful only if a uniqueness check was done. See actn.*/ int unique; } actn_r; @@ -171,6 +205,7 @@ msplit_r msplit(matrix* Dm, matrix* Dp, int* mask, matrix* M, matrix* L0, matrix* L, int* ipl, int ipCount, int* dpl, int dpCount, int** TD, int* TDCount); /*MSPLIT - split transitions to make a Petri net PT-ordinary. +Original Matlab Usage: [DF, DFM, DFP] = msplit(DM, DP) [DF, DFM, DFP] = msplit(DM, DP, mask) @@ -192,11 +227,27 @@ through transition split. Used in DP. +Usage In C: +msplit_r msplit(matrix *Dm, matrix *Dp, int *mask, matrix *M, matrix *L0, +matrix *L, int *ipl, int ipCount, int *dpl, int dpCount, int **TD, int *TDCount) +Parameters have the same meaning and usage as in Matlab with the following +differences and notes: +* Mask: Integer array. Same as "mask" in matlab. Not required. If not present + Mask is assumed to be all 1's. +* ipl, ipCount: Pointer to an integer array and the number of elements in the + array, respectively. Same as ipl in Matlab. Not required. If not present, + defaults to an array containing the index of each place in the net. This also + forces dpl to default to empty. Note that the sum of ipCount and dpCount must + be the same as the total number of places in the Petri net. +* dpl, dpCount: Pointer to an integer array and the number of elements in the + array, respectively. Same as dpl in Matlab. See ipl, ipCount for defaults. + Written for Matlab by Marian V. Iordache, mar...@le.... Converted to C by Marian V. Iordache and Stephen Camp, ste...@le....*/ ilpadm_r ilpadm(matrix* L, int* b, matrix* D, int TucCount, int* Tuc, int TuoCount, int* Tuo, int* m0); /*ILP_ADM - transformation to admissible constraints based on linear integer programming +Original Matlab usage: [La, ba, R1, R2, how, dhow] = ilp_adm(L, b, D, Tuc, Tuo, m0, vrb) The function transforms a marking constraint L*m <= b to an admissible @@ -218,6 +269,20 @@ Use m0 = [] or only the first five arguments if the initial marking is not of interest. +Usage in C: +ilpadm_r ilpadm(matrix* L, int* b, matrix* D, int TucCount, int* Tuc, int TuoCount, +int* Tuo, int* m0); +The parameters have the same meaning as in Matlab with the following notes and +exceptions: +* b is an integer array, used as in matlab. If not present defaults to all zeroes. +* TucCount, Tuc. The number of elements in and an array of integers containing + the list of uncontrollable transition indices, respectively. Not required. + Same as Tuc in Matlab. +* TuoCount, Tuo. The same as Tuc but for unobservable transitions. Same as Tuo + in Matlab. +* The vrb parameter from Matlab has been dispensed with. ilpadm now uses the + program-wide verbosity level. + Written for Matlab by Marian V. Iordache, mar...@le.... Converted to C by Marian V. Iordache and Stephen Camp, ste...@le....*/ @@ -241,7 +306,7 @@ ipsolve_r ipsolve(matrix* L, double* B, double* f, short int *IntList, double *ub, double *lb, short int *ctype); /* ipsolve - Interface to the Mixed Integer Program Solver LP_SOLVE - +Original Usage in Matlab: [res, how] = ipsolve(L, B, f, intlist, ub, lb, ctype) The function minimizes f'*x subject to Lx >= B and lb <= x <= ub. x(i) is an integer if intlist(i) is not zero. @@ -266,6 +331,12 @@ Another integer program solver is SOLVE_IP. +Usage in C: +ipsolve_r ipsolve(matrix* L, double* B, double* f, short int *IntList, double *ub, double *lb, short int *ctype) +All parameters have the same meaning as in Matlab. B, f, IntList, ub, and lb are +all pointers that should point to the first element of an array of the appropriate +length or be given as a null pointer. + This interface to the LP_SOLVE package has been written by Marian V. Iordache, mar...@le.... It was converted to C by Marian V. Iordache and Stephen Camp, ste...@le....*/ @@ -295,7 +366,7 @@ The function returns the structure that corresponds to the supervised Petri net, and the initial marking of the supervised Petri net (ms0), (the argument m0 specifies the initial marking of the plant Petri net.) -The initial firing vector v0 is assumed to be 0. The syntax is: +The initial firing vector v0 is assumed to be 0. The Matlab syntax is: [Df^-, Df^+, ms0] = linenf(pn, L, b, F, C) @@ -380,6 +451,15 @@ The disadvantage of using a precomputed plant coverability graph is that it is more likely to have a v(i) equal to -1. +Usage in C: +linenf_r linenf(matrix* Dm, matrix* Dp, matrix* L, int* b, int* m0, matrix* F, matrix* C, int TucCount, int* Tuc, int TuoCount, int* Tuo) +All parameters have the same names as their counterparts in Matlab. Parameters +in matlab that were vectors are passed in C as array pointers. The variable-length +vectors Tuc and Tuo are given in two parts, an integer (TucCount/TuoCount) specifying +the length of the array followed by a pointer (Tuc/Tuo) to the first element of the +array. The form of the function call making use of a pnobj structure is no longer +valid. + See LINENF and PNCGRAPH. Written for Matlab by Marian V. Iordache, mar...@le.... @@ -390,6 +470,7 @@ /* NLTRANS - Find all transitions that cannot be made live +Usage in Matlab: [nlt] = nltrans(D) [nlt] = nltrans(D^-, D^+, X) @@ -400,6 +481,14 @@ other reasons. E.g. X = [1, 3, 6] indicates the transitions t_1, t_3 and t_6. +Usage in C: +nltrans_r nltrans(matrix* D, int* UnraisableTransitions, int urtCount) +D is the same as D in Matlab. The function no longer accepts separate D+ and D- +matrices. X in Matlab corresponds to the array pointer UnraisableTransitions. +UnraisableTransitions should be the pointer to the array containing the +transitions to be assumed unraisable, and urtCount should be set to the number +of elements in the array. + Written by Marian V. Iordache, mar...@le.... Converted to C by Marian V. Iordache and Stephen Camp, ste...@le... */ @@ -408,6 +497,7 @@ /* PN2ACPN - Transforms a Petri net to an asymmetric choice Petri net +Matlab Usage: [Df, Dmf, Dpf] = pn2acpn(D) [Df, Dmf, Dpf] = pn2acpn(Dm, Dp) @@ -428,6 +518,13 @@ See MSPLIT. +C Usage: +pn2acpn_r pn2acpn(matrix* Dm, matrix* Dp, int* Mask, matrix* MX, matrix* L0, +matrix* L, int *ipl, int ipCount, int* dpl, int dpCount) +Dm and Dp are the same as in Matlab. The function no longer accepts a single +incidence matrix D. The variable-length vectors ipl and dpl in Matlab should +be passed as a pointer to the integer array followed by the length of the +array. Written by Marian V. Iordache, mar...@le... M. Iordache -- Sep. 4, 2000 @@ -441,6 +538,7 @@ /* PN2EACPN - Transforms a Petri net to an extended asymmetric choice Petri net +Matlab Usage: [Df, Dmf, Dpf] = pn2eacpn(D) [Df, Dmf, Dpf] = pn2eacpn(Dm, Dp) @@ -466,6 +564,15 @@ See MSPLIT. +C Usage: +pn2eacpn_r pn2eacpn(matrix* Dm, matrix* Dp, int* Mask, matrix* MX, matrix* L0, +matrix* L, int *ipl, int ipCount, int* dpl, int dpCount, int** TD, int* TDCount) +Dm and Dp are the same as in Matlab. The function no longer accepts a single +incidence matrix D. The variable-length vectors ipl and dpl in Matlab should +be passed as a pointer to the integer array followed by the length of the +array. + + Written for Matlab by Marian V. Iordache, mio...@nd... Original Matlab code extended the Matlab pn2acpn code written on M. Iordache -- Sep. 4, 2000 @@ -481,6 +588,7 @@ chkcons_r chkcons(matrix* L0, int* B0, matrix* l0, int b0); /* +Matlab Usage: res = chk_con2(L,B,l,b) Checks consistency of the set of constraints Lx >= B and lx< b, @@ -492,8 +600,15 @@ that Lx >= B and lx < b. If res is empty, then the constraint lx >= b is redundant for Lx >= B. -The C implementation of chkcons currently is an implementation of CHK_CON2.M from the original Matlab package. +C Usage: +chkcons_r chkcons(matrix* L0, int* B0, matrix* l0, int b0) +The parameters have the same names and meanings as in Matlab. Either the pair L0 +& l0 or the pair B0 and b0 is required. Both pairs can be given. If B0 is a null +pointer, the value of b0 is ignored. +The C implementation of chkcons currently is an implementation of CHK_CON2.M +from the original Matlab package. + CHK_CON2 is the old version of CHK_CONS. It is expected to be slower than CHK_CONS. However, CHK_CON2 is simpler, and so it may be more reliable. @@ -506,6 +621,7 @@ reduce_r reduce(matrix* L0, int* B0); /* +Matlab usage: [Lf, Bf, ind, how] = reduce(L,B) This function removes redundant constraints of Lx>=B, where x @@ -515,6 +631,10 @@ See also CHK_CONS, IP_SOLVE. +C Usage: +reduce_r reduce(matrix* L0, int* B0) +L0 and B0 are L and B, respectively, from the Matlab version. + Written for Matlab by Marian V. Iordache, mar...@le.... Converted to C by Marian Iordache and Stephen Camp, ste...@le.... */ @@ -522,7 +642,7 @@ actn_r actn(matrix* Dm, matrix* Dp, int* X, int XCount, matrix *Dcm, matrix *Dcp, int update, int checkUnique); /* ACTN - The active subnet of a Petri net - +Matlab usage: [Dma, Dpa, Dmra, Dpra] = actn(Dm, Dp) [Dma, Dpa, Dmra, Dpra] = actn(Dm, Dp, X) @@ -547,6 +667,15 @@ See also NLTRANS. +C Usage: +actn_r actn(matrix* Dm, matrix* Dp, int* X, int XCount, matrix *Dcm, matrix *Dcp, int update, int checkUnique) +Parameters have the same names as in Matlab with a few exceptions. The variable-length +vector X is passed as the pointer to the integer array (X) followed by the number of +elements in the array (XCount). The additional parameter, checkUnique, should be +nonzero if the user wants to run a uniqueness check. Note that the uniqueness check +is time-consuming. If the check is not run, the value if "unique" in the result +structure will be set to 0 regardless of the actual state of the result. + Written for Matlab by Marian V. Iordache, mar...@le.... Converted to C by Marian Iordache and Stephen Camp, ste...@le.... */ @@ -555,6 +684,8 @@ /* TACTN - Computes a T-minimal active subnet of a Petri net +Matlab usage: + [Dma, Dpa, Dmra, Dpra, TA] = tactn(Dm, Dp, T, Z) [Dma, Dpa, Dmra, Dpra, TA, unique] = tactn(Dm, Dp, T, Z) @@ -603,6 +734,18 @@ See also ACTN and NLTRANS. +C Usage: +tactn_r tactn(matrix* Dm, matrix* Dp, int* IncludeT, int IncludeTCount, int* ExcludeT, int ExcludeTCount, matrix *Dcm, matrix *Dcp, int checkUnique) + +Parameters have the same names as in Matlab with a few exceptions. IncludeT and +ExcludeT replace the variable-length vectors T and Z. They should be given as +the pointer to the integer array (IncludeT or ExcludeT) followed by the number of +elements in the array (IncludeTCount or ExcludeTCount). The additional parameter, +checkUnique, should be nonzero if the user wants to run a uniqueness check. Note +that the uniqueness check is time-consuming. If the check is not run, the value +of "unique" in the result structure will be set to 0 regardless of the actual +state of the result. + Written for Matlab by Marian V. Iordache, mar...@le... Marian V. Iordache, Sep. 5, 2000. @@ -626,6 +769,13 @@ flag = (S == siphon) flx = sum(flag == 0) (i.e. flx is nonzero if a column of S is not a siphon) +C Usage: +issiph_r issiph(matrix *Dm, matrix *Dp, void *PlaceSet, int MultiplePlaceSets) +The parameter S in Matlab is equivalent to the parameter PlaceSet in C. +If MultiplePlaceSets is nonzero, PlaceSet is interpreted as a pointer to a matrix +formated as described above. Otherwise, PlaceSet is interpreted as a pointer +to an integer array, where each integer is a flag as described above. + Written for Matlab by Marian V. Iordache, mar...@le.... Converted to C by Marian V. Iordache and Stephen Camp, ste...@le.... */ Modified: spnbox/tests/StructuredIO.c =================================================================== --- spnbox/tests/StructuredIO.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/StructuredIO.c 2009-07-14 21:32:17 UTC (rev 197) @@ -8,7 +8,7 @@ name = any string without whitespace. TYPE = one of: matrix A matrix. - matrix* A pointer to a matrix. + indexarray An array of indexes (treated like an integer array). arrayi An array of integers stored as a pointer. arrayd An array of doubles stored as a pointer. arraya An array of arrays of integers. @@ -35,7 +35,7 @@ static double* ReadDblArray(FILE* file, int* length); static int* ReadIntArray(FILE* file, int* length); static void TrimWhitespace(char* string); - +static void Help(char* helpstring, Parameter* Param, int ParamCount); int ParseStructure(FILE *file, char* DataDescription, int** FilledMask, MemoryManager* Memory, ...) { MemoryManager memory; @@ -106,14 +106,21 @@ { fgets(Line, 128, file); LineStart = Line; - while (isspace(*LineStart) && *LineStart != '\0') LineStart++; - printf("%s", LineStart); + TrimWhitespace(Line); + printf("%s\n", LineStart); } /*If it is a line comment read the remainder of the line and do nothing.*/ else if (! strcmp(Token, "rem")) { fgets(Line, 128, file); } + /*If it is a request for help, read the rest of the line and show the help.*/ + else if (! strcmp(Token, "help")) + { + fgets(Line, 128, file); + TrimWhitespace(Line); + Help(Line, Param, ParamCount); + } /*Otherwise try to parse it as a user-defined token.*/ else { @@ -635,4 +642,154 @@ } } string[test + 1] = '\0'; -} \ No newline at end of file +} + +/*This is called when the user makes a help request.*/ +void Help(char* helpstring, Parameter* Param, int ParamCount) +{ + /*If the help string is empty or a null pointer, display the parameter help.*/ + if ((! helpstring) || strlen(helpstring) == 0) + { + printf("This program uses the Structured IO routines. These routines allow a\n"); + printf("test problem or other group of data to be entered in a human-readable\n"); + printf("format. Data for each problem is entered as a series of keywords,\n"); + printf("corresponding to variables used for the problem. Each keyword is followed\n"); + printf("by the data that will fill that variable. There are also predefined\n"); + printf("keywords that control the IO routines themselves.\n\n"); + printf("Keywords and types used in this program are shown below. For information\n"); + printf("about a specific data type, such as how to enter data of that type, enter\n"); + printf("\"help typename\". For information about one of the predefined keywords,\n"); + printf("enter \"help keyword\".\n"); + printf("Predefined keywords: echo, rem, help, done, quit\n"); + printf("Program-defined keywords:\n"); + /*Print keywords and types.*/ + int i; + char* typestring; + for (i = 0; i < ParamCount; i++) + { + if (! strcmp(Param[i].Type, "matrix")) typestring = "matrix"; + if (! strcmp(Param[i].Type, "arrayi")) typestring = "integer array"; + if (! strcmp(Param[i].Type, "arrayd")) typestring = "double array"; + if (! strcmp(Param[i].Type, "arraya")) typestring = "array of arrays"; + if (! strcmp(Param[i].Type, "indexarray")) typestring = "integer array"; + if (! strcmp(Param[i].Type, "int")) typestring = "integer"; + if (! strcmp(Param[i].Type, "double")) typestring = "double"; + if (! strcmp(Param[i].Type, "string")) typestring = "string"; + printf("\"%s\" of type \"%s\".\n", Param[i].Name, typestring); + } + } + else if (! strcmp(helpstring, "echo")) + { + printf("echo: Predefined keyword. Upon encountering an echo request, the program\n"); + printf("reads the remainder of the line and prints it to the console output. Used\n"); + printf("primarily with scripts.\n"); + } + else if (! strcmp(helpstring, "rem")) + { + printf("rem: Predefined keyword. Any line beginning with the rem keyword is\n"); + printf("ignored. Used for comments in scripts.\n"); + } + else if (! strcmp(helpstring, "help")) + { + printf("help: Predefined keyword. The remainder of the line is read. If the line\n"); + printf("is empty, displays the general help and list of keywords. If the line\n"); + printf("contains a predefined keyword or a type name, help on that item is\n"); + printf("displayed. Note there is no built-in help for program-defined keywords.\n"); + } + else if (! strcmp(helpstring, "done")) + { + printf("done: Marks the end of a set of input data. The IO routines parse data\n"); + printf("in sets, where each set is the data for a problem. When this keyword is\n"); + printf("encountered, the IO routines return control to the main program so that\n"); + printf("the data can be processed. Note that \"done\" must be used before any\n"); + printf("data is processed. If the quit keyword or an error is encountered before\n"); + printf("\"done\", none of that set of data will be processed.\n"); + } + else if (! strcmp(helpstring, "quit")) + { + printf("quit: predefined kewyword. Marks the end of problems. The IO routines\n"); + printf("return control to the main program and allow it to shut down when this\n"); + printf("keyword is encountered. Note that any data that has not been marked for\n"); + printf("processing via a \"done\" keyword at the time this keyword is encountered\n"); + printf("will never be processed.\n"); + } + else if (! strcmp(helpstring, "matrix")) + { + printf("matrix: data type. To enter data of type matrix, specify the keyword for the\n"); + printf("data being entered, followed by the number of rows, followed by the number of\n"); + printf("columns, followed by each element of the array.\n"); + printf("All the values should be separated by whitespace (spaces, tabs, newlines, etc.)\n"); + printf("The kind or amount of whitespace is irrelevant. This allows the user to enter\n"); + printf("the data in a visually pleasing manner.\n"); + printf("Example usage: Filling a matrix with keyword 'M' with a 3 x 3 identity:\n"); + printf("M 3 3\n"); + printf("1 0 0\n0 1 0\n0 0 1\n"); + } + else if (! strcmp(helpstring, "integer array")) + { + printf("integer array: data type. An array of integers. To enter data, specify\n"); + printf("the keyword for the data, followed by the number of elements in the\n"); + printf("array, followed by each element of the array.\n"); + printf("All the values should be separated by whitespace (spaces, tabs, newlines, etc.)\n"); + printf("The kind or amount of whitespace is irrelevant. This allows the user to enter\n"); + printf("the data in a visually pleasing manner.\n"); + printf("Example usage: Filling an integer array with keyword 'A' with a sequence of 3:\n"); + printf("A 3\n1 2 3\n"); + } + else if (! strcmp(helpstring, "double array")) + { + printf("double array: data type. An array of doubles (floating-point or decimal\n"); + printf("numbers. To enter, give the keyword followed by the number of elements in\n"); + printf("the array followed by each element of the array.\n"); + printf("All the values should be separated by whitespace (spaces, tabs, newlines, etc.)\n"); + printf("The kind or amount of whitespace is irrelevant. This allows the user to enter\n"); + printf("the data in a visually pleasing manner.\n"); + printf("Example usage: Filling a double array with keyword 'A' with a sequence\n"); + printf("of 4 elements counting by 0.25:\n"); + printf("A 4\n0.25 0.5 0.75 1\n"); + } + else if (! strcmp(helpstring, "array of arrays")) + { + printf("array of arrays: data type. An array each element of which is itself an\n"); + printf("array. To enter, give the keyword followed by the number of arrays\n"); + printf("followed by each array. Each array should be entered as the number of\n"); + printf("elements in the array followed by the elements of the array. array of\n"); + printf("arrays only accepts integral numbers, not floating-point (decimal).\n"); + printf("All the values should be separated by whitespace (spaces, tabs, newlines, etc.)\n"); + printf("The kind or amount of whitespace is irrelevant. This allows the user to enter\n"); + printf("the data in a visually pleasing manner.\n"); + printf("Example usage: Filling an array of arrays with keyword AROA with 3 arrays,\n"); + printf("The first containing the elements [1, 2, 3], the second containing [4, 5],\n"); + printf("and the third containing only one element, [6]:\n"); + printf("AROA 3\n3 1 2 3\n2 4 5\n1 6\n"); + } + else if (! strcmp(helpstring, "string")) + { + printf("string: data type. This is just a piece of text up to 127 characters long.\n"); + printf("To enter, give the keyword followed by the text on the same line. The rest\n"); + printf("of the line will be read, leading and trailing whitespace will be removed\n"); + printf("and what is left is the text.\n"); + printf("Example usage: Filling a string with keyword 's' with the text \"hello world\":\n"); + printf("s hello world\n"); + } + else if (! strcmp(helpstring, "integer")) + { + printf("integer: data type. A single integer. To enter, give the keyword followed by\n"); + printf("the value.\n"); + printf("Example usage: Filling an integer with keyword 'i' with the value 4:\n"); + printf("i 4\n"); + } + else if(! strcmp(helpstring, "double")) + { + printf("integer: data type. A single double (floating point or decimal number). To\n"); + printf("enter, give the keyword followed by the value.\n"); + printf("Example usage: Filling double with keyword 'd' with the value 3.14159:\n"); + printf("d 3.14159\n"); + } + else + { + printf("Unrecognized help request. Type \"help\" on a line by itself to see the\n"); + printf("general help.\n"); + } + printf("\n"); +} Modified: spnbox/tests/StructuredIO.h =================================================================== --- spnbox/tests/StructuredIO.h 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/StructuredIO.h 2009-07-14 21:32:17 UTC (rev 197) @@ -2,6 +2,7 @@ #define STRUCTUREDIO #include "../MemoryManager.h" + int ParseStructure(FILE *file, char* DataDescription, int** FilledMask, MemoryManager* Memory, ...); /*ParseStructure fills the optional parameters with values read from file. Data types are described by the string DataDescription. If FilledMask is @@ -27,6 +28,7 @@ screen. This can be used for comments, problem numbers, and so forth. rem rem is like echo except that no text is printed to the screen. Used for comments. +help Displays a help message by calling ShowHelp. The syntax of DataDescription is as follows: TYPE NAME[,TYPE NAME...] Modified: spnbox/tests/test-actn.c =================================================================== --- spnbox/tests/test-actn.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-actn.c 2009-07-14 21:32:17 UTC (rev 197) @@ -13,7 +13,7 @@ char OutputDesc[] = "matrix Da, matrix Dma, matrix Dpa, matrix Dra, matrix Dmra, matrix Dpra, arrayi TA, int Unique"; /*Get the input file.*/ - if (! (input = GetInput(argc, argv))) return 0; + if (! (input = ParseCmdLine(argc,argv))) return 0; memory = CreateMemoryManager(10, 10, 0, 0); while (ParseStructure(input, InputDesc, &InFilled, &memory, &D, &Dm, &Dp, &Dc, &Dcm, &Dcp, &X, &XCount, &update)) Modified: spnbox/tests/test-extendedmatrix.c =================================================================== --- spnbox/tests/test-extendedmatrix.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-extendedmatrix.c 2009-07-14 21:32:17 UTC (rev 197) @@ -36,12 +36,6 @@ int main(int argc, char* argv[]) { FILE* input; - - if (! (input = GetInput(argc, argv))) - { - return 1; - } - char Desc[] = "string optimization, string operation, int mode, matrix A, matrix B, int row, int column, int rows, int columns, int repetitions, int size, string speedtest"; char Operation[128], optimization[128], speedtest[128]; matrix A, B; @@ -49,6 +43,11 @@ int Mode, Row, Column, Rows, Columns, Reps, Size, Optimized, SpeedTest; MemoryManager mem; + if (! (input = ParseCmdLine(argc,argv))) + { + return 0; + } + mem = CreateMemoryManager(5, 2, 0, 0); SetDefaults(optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size, speedtest); while (ParseStructure(input, Desc, &Filled, &mem, optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size)) Modified: spnbox/tests/test-ilpadm.c =================================================================== --- spnbox/tests/test-ilpadm.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-ilpadm.c 2009-07-14 21:32:17 UTC (rev 197) @@ -21,9 +21,9 @@ /*Set the verbosity level to maximum*/ setverbose(VRB_MAX); - if (! (input = GetInput(argc, argv))) + if (! (input = ParseCmdLine(argc, argv))) { - return 1; + return 0; } while (ParseStructure(input, InDesc, &InFilled, &mem, &D, &Tuc, &TucCount, &Tuo, &TuoCount, &L, &B, &BCount, &m0, &m0Count)) Modified: spnbox/tests/test-ipsolve.c =================================================================== --- spnbox/tests/test-ipsolve.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-ipsolve.c 2009-07-14 21:32:17 UTC (rev 197) @@ -20,9 +20,9 @@ MemoryManager mem; /*Get the input file.*/ - if (! (input = GetInput(argc, argv))) + if (! (input = ParseCmdLine(argc,argv))) { - return 1; + return 0; } mem = CreateMemoryManager(10, 10, 0, 0); Modified: spnbox/tests/test-isadm.c =================================================================== --- spnbox/tests/test-isadm.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-isadm.c 2009-07-14 21:32:17 UTC (rev 197) @@ -14,9 +14,9 @@ int bCount, m0Count, TucCount, TuoCount; /*Get a pointer to the input file.*/ - if (! (input = GetInput(argc, argv))) + if (! (input = ParseCmdLine(argc,argv))) { - return 1; + return 0; } memory = CreateMemoryManager(5, 6, 0, 0); Modified: spnbox/tests/test-issiph.c =================================================================== --- spnbox/tests/test-issiph.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-issiph.c 2009-07-14 21:32:17 UTC (rev 197) @@ -14,9 +14,9 @@ matrix D, Dm, Dp, PlaceSet; /*Get a pointer to the input file.*/ - if (! (input = GetInput(argc, argv))) + if (! (input = ParseCmdLine(argc,argv))) { - return 1; + return 0; } memory = CreateMemoryManager(5, 6, 0, 0); Modified: spnbox/tests/test-linenf.c =================================================================== --- spnbox/tests/test-linenf.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-linenf.c 2009-07-14 21:32:17 UTC (rev 197) @@ -18,9 +18,9 @@ int i, Constraints; /*Get the input file pointer.*/ - if (! (input = GetInput(argc, argv))) + if (! (input = ParseCmdLine(argc,argv))) { - return 1; + return 0; } memory = CreateMemoryManager(15, 15, 0, 0); Modified: spnbox/tests/test-matrixmath.c =================================================================== --- spnbox/tests/test-matrixmath.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-matrixmath.c 2009-07-14 21:32:17 UTC (rev 197) @@ -26,9 +26,7 @@ int main(int argc, char* argv[]) { FILE* input; - - input = GetInput(argc, argv); - + char Desc[] = "string option, string operation, matrix A, matrix B, arrayi C, arrayi D, int row, int column"; char Operation[128], Option[128]; matrix A, B; @@ -36,6 +34,7 @@ int CCount, DCount, Row, Column; MemoryManager mem; + if (! (input = ParseCmdLine(argc,argv))) return 0; mem = CreateMemoryManager(5, 2, 0, 0); while (ParseStructure(input, Desc, &Filled, &mem, Option, Operation, &A, &B, &C, &CCount, &D, &DCount, &Row, &Column)) Modified: spnbox/tests/test-msplit.c =================================================================== --- spnbox/tests/test-msplit.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-msplit.c 2009-07-14 21:32:17 UTC (rev 197) @@ -21,23 +21,7 @@ msplit_r Return; FILE* Input; - if (argc > 1) - { - if (Input = fopen(argv[1], "r")) - { - printf("Reading from file '%s'...\n", argv[1]); - } - else - { - printf("ERROR! Could not open file '%s' for read-only access.\n", argv[1]); - return 1; - } - } - else - { - Input = stdin; - printf("Reading from keyboard...\n"); - } + if (! (Input = ParseCmdLine(argc,argv))) return 0; memory = CreateMemoryManager(10, 10, 0, 0); Modified: spnbox/tests/test-nltrans.c =================================================================== --- spnbox/tests/test-nltrans.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-nltrans.c 2009-07-14 21:32:17 UTC (rev 197) @@ -9,23 +9,10 @@ MemoryManager mem; nltrans_r solution; - if (argc > 1) + if (! (input = ParseCmdLine(argc, argv))) { - if (input = fopen(argv[1], "r")) - { - printf("Taking input from file '%s'...", argv[1]); - } - else - { - printf("Failed to open file '%s'! Terminating.", argv[1]); - return 1; - } + return 0; } - else - { - input = stdin; - printf("Taking input from console..."); - } mem = CreateMemoryManager(5, 5, 0, 0); while (ParseStructure(input, "matrix D, arrayi URT", &Filled, &mem, &D, &URT, &urtCount)) Modified: spnbox/tests/test-pn2acpn.c =================================================================== --- spnbox/tests/test-pn2acpn.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-pn2acpn.c 2009-07-14 21:32:17 UTC (rev 197) @@ -20,23 +20,10 @@ /*Get the input stream. If there was a command line argument, treat it as a filename and attempt to open it for read access, terminating on failure. Otherwise set stdin as the input stream.*/ - if (argc > 1) + if (! (input = ParseCmdLine(argc, argv))) { - if (input = fopen(argv[1], "r")) - { - printf("Taking input from file '%s'...\n", argv[1]); - } - else - { - printf("Failed to open file '%s' for read access! Terminating.\n", argv[1]); - return 1; - } + return 0; } - else - { - input = stdin; - printf("Taking input from console...\n"); - } /*Initialize the memory manager. We don't know how many matrices and arrays we'll need so just pick a nice round number as the initial address block size Modified: spnbox/tests/test-pn2eacpn.c =================================================================== --- spnbox/tests/test-pn2eacpn.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-pn2eacpn.c 2009-07-14 21:32:17 UTC (rev 197) @@ -21,23 +21,10 @@ /*Get the input stream. If there was a command line argument, treat it as a filename and attempt to open it for read access, terminating on failure. Otherwise set stdin as the input stream.*/ - if (argc > 1) + if (! (input = ParseCmdLine(argc, argv))) { - if (input = fopen(argv[1], "r")) - { - printf("Taking input from file '%s'...\n", argv[1]); - } - else - { - printf("Failed to open file '%s' for read access! Terminating.\n", argv[1]); - return 1; - } + return 0; } - else - { - input = stdin; - printf("Taking input from console...\n"); - } /*Initialize the memory manager. We don't know how many matrices and arrays we'll need so just pick a nice round number as the initial address block size Modified: spnbox/tests/test-reduce.c =================================================================== --- spnbox/tests/test-reduce.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-reduce.c 2009-07-14 21:32:17 UTC (rev 197) @@ -15,7 +15,10 @@ char OutputDesc[] = "matrix Lf, arrayi Bf, arrayi RowsKept, int How"; /*Get the input file.*/ - if (! (input = GetInput(argc, argv))) return 0; + if (! (input = ParseCmdLine(argc, argv))) + { + return 0; + } memory = CreateMemoryManager(4, 1, 0, 0); while (ParseStructure(input, InputDesc, &InFilled, &memory, &L, &B, &BCount)) Modified: spnbox/tests/test-supervis.c =================================================================== --- spnbox/tests/test-supervis.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-supervis.c 2009-07-14 21:32:17 UTC (rev 197) @@ -13,9 +13,9 @@ matrix D, Dm, Dp, L, Df; /*Get the input file.*/ - if (! (input = GetInput(argc, argv))) + if (! (input = ParseCmdLine(argc,argv))) { - return 1; + return 0; } mem = CreateMemoryManager(1, 5, 0, 0); Modified: spnbox/tests/test-tactn.c =================================================================== --- spnbox/tests/test-tactn.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test-tactn.c 2009-07-14 21:32:17 UTC (rev 197) @@ -13,7 +13,7 @@ char OutputDesc[] = "matrix Da, matrix Dma, matrix Dpa, matrix Dra, matrix Dmra, matrix Dpra, arrayi TA, int Unique"; /*Get the input file.*/ - if (! (input = GetInput(argc, argv))) return 0; + if (! (input = ParseCmdLine(argc,argv))) return 0; memory = CreateMemoryManager(10, 10, 0, 0); while (ParseStructure(input, InputDesc, &InFilled, &memory, &D, &Dm, &Dp, &Dc, &Dcm, &Dcp, &ExcludeT, &ExcludeTCount, &IncludeT, &IncludeTCount)) Modified: spnbox/tests/test.c =================================================================== --- spnbox/tests/test.c 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test.c 2009-07-14 21:32:17 UTC (rev 197) @@ -14,7 +14,7 @@ verbose = vrb; } -FILE* GetInput(int argc, char* argv[]) +FILE* ParseCmdLine(int argc, char* argv[]) { FILE* file; if (argc > 1) @@ -32,10 +32,11 @@ } else { - printf("Taking input from console...\n"); + printf("Taking input from console. Type \"help\" to see a description of\n"); + printf("the input format.\n"); return stdin; } -} +} int HasSelfLoops(matrix* Dm, matrix* Dp) { Modified: spnbox/tests/test.h =================================================================== --- spnbox/tests/test.h 2009-07-14 15:31:42 UTC (rev 196) +++ spnbox/tests/test.h 2009-07-14 21:32:17 UTC (rev 197) @@ -16,8 +16,10 @@ in test.c*/ void setverbose(int vrb); -/*Get the file pointer that input will be taken from.*/ -FILE* GetInput(int argc, char* argv[]); +/*If the command line argument is the word "help", show the program help. If +the argument is a filename, open it for read and return a pointer. If there is +no command line argument return a pointer to stdin.*/ +FILE* ParseCmdLine(int argc, char* argv[]); /*Determine if the given i/o matrices have self-loops.*/ int HasSelfLoops(matrix* Dm, matrix* Dp); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-14 15:31:45
|
Revision: 196 http://pntool.svn.sourceforge.net/pntool/?rev=196&view=rev Author: StephenCamp Date: 2009-07-14 15:31:42 +0000 (Tue, 14 Jul 2009) Log Message: ----------- Split the functions in matrixmath.c into two files: Matrix mathematics remain in matrixmath.c. Manipulation functions such as row insertion and removal have been moved to extendedmatrix.c. The test routines and makefiles have been updated appropriately. The manipulation functions have been updated to have a more consistent interface. Each function now takes a "mode" parameter that determines whether it is to allocate space for and return a completely new matrix and leave the operands untouched or modify the operands directly. supervis.c has been updated to use the new function definition. Updated the readme. Modified Paths: -------------- spnbox/Makefile spnbox/README.txt spnbox/matrixmath.c spnbox/matrixmath.h spnbox/supervis.c spnbox/tests/Makefile spnbox/tests/test-matrixmath.c spnbox/tests/test-matrixmath.txt Added Paths: ----------- spnbox/extendedmatrix.c spnbox/extendedmatrix.h spnbox/tests/test-extendedmatrix.c spnbox/tests/test-extendedmatrix.txt Modified: spnbox/Makefile =================================================================== --- spnbox/Makefile 2009-07-13 18:01:14 UTC (rev 195) +++ spnbox/Makefile 2009-07-14 15:31:42 UTC (rev 196) @@ -3,7 +3,7 @@ COMPILER=gcc -g -all: actn.o chkcons.o ilpadm.o ipslv.o ipsolve.o isadm.o issiph.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a +all: actn.o chkcons.o extendedmatrix.o ilpadm.o ipslv.o ipsolve.o isadm.o issiph.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a actn.o: actn.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c actn.c @@ -11,6 +11,9 @@ chkcons.o: chkcons.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h $(COMPILER) -c chkcons.c +extendedmatrix.o: extendedmatrix.c extendedmatrix.h ../pnheaders/general.h ../pnheaders/matrix.h + $(COMPILER) -c extendedmatrix.c + ilpadm.o: ilpadm.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h $(COMPILER) -c ilpadm.c @@ -62,3 +65,7 @@ clean: rm -f *.o *.a cd ../third-party/lp_solve_5.5; make -f Makefile.Linux clean + +clean-partial: + rm -f *.o + Modified: spnbox/README.txt =================================================================== --- spnbox/README.txt 2009-07-13 18:01:14 UTC (rev 195) +++ spnbox/README.txt 2009-07-14 15:31:42 UTC (rev 196) @@ -12,7 +12,7 @@ make <functionname> This will generate an executable called <functionname>.exe. make all will generate test executables for all spnbox functions. -To test the various functions in the matrixmath.c file, use make matrixmath. +To test the various functions in the matrixmath.c file, use make matrixmath. To test the functions in the extendedmatrix.c file, use make extendedmatrix. For all with such test programs except that ipslv, the test program is implemented as a program that will read from an input stream containing text in a human-readable format, interpret the text as parameters to the function, make a function call, and display the results. For format specifications, see the comments in StructuredIO.c/h. @@ -35,11 +35,11 @@ - deallocation.c: This implements functions to deallocate the structures returned by SPNBOX functions. - Makefile: This is the main makefile. When used without a target it builds - object files that implement all SPNBOX functionality. It can take as a target - the command "clean", upon reciept of which it removes all object files, all - library (*.a) files, moves to the third-party/lp_solve_5.5/ directory, and - executes the linux-targeted makefile to clean the lpsolve libraries and - intermediate files. + object files that implement all SPNBOX functionality. + Use "make clean" to remove all object files, all library (*.a) files, and + execute the clean command for the lpsolve library in the third-party/lp_solve_5.5 + directory. + Use "make clean-partial" to remove all object files. - Each of the other files corresponds to a single SPNBOX function. tests subdirectory: Added: spnbox/extendedmatrix.c =================================================================== --- spnbox/extendedmatrix.c (rev 0) +++ spnbox/extendedmatrix.c 2009-07-14 15:31:42 UTC (rev 196) @@ -0,0 +1,341 @@ +#include "../pnheaders/general.h" +#include "../pnheaders/matrix.h" +#include "matrixmath.h" +#include "extendedmatrix.h" + +static matrix InsertRowsCopy(matrix* outer, matrix* inner, int start, int mode); +static matrix InsertRowsOrig(matrix* outer, matrix* inner, int start); +static matrix RemoveRowsCopy(matrix* m, int row, int rows, int mode); +static matrix RemoveRowsOrig(matrix* m, int row, int rows); +static matrix InsertNullRowsCopy(matrix *m, int row, int rows, int mode); +static matrix InsertNullRowsOrig(matrix *m, int row, int rows); + +matrix InsertRows(matrix* outer, matrix* inner, int start, int mode) +{ + matrix null; + + /*Check parameters. None of the pointers can be null.*/ + if(! (outer && inner)) + { + merror(0, "InsertRows/Columns: One of the operands is a null pointer"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*inner and outer must have the same number of columns.*/ + if (NumberOfColumns(*inner) != NumberOfColumns(*outer)) + { + merror(0, "InsertRows/Columns: The operands do not have the same number of columns/rows"); + AllocateMatrix(&null, 0, 0); + return null; + } + + /*If start is negative, default to adding to the end.*/ + if (start < 0) start = NumberOfRows(*outer); + /*start cannot point to a row farther out than the first possible new row*/ + if (start > NumberOfRows(*outer)) + { + merror(0, "InsertRows/Columns: The index of the first inserted row/column is out of range"); + AllocateMatrix(&null, 0, 0); + return null; + } + + /*If mode is 0 or positive, we are writing to a copy.*/ + if (mode >= 0) + { + return InsertRowsCopy(outer, inner, start, mode); + } + /*Otherwise, we want to actually merge the matrices.*/ + else + { + return InsertRowsOrig(outer, inner, start); + } +} + +matrix InsertColumns(matrix* outer, matrix* inner, int start, int mode) +{ + /*This is the column analogue of InsertRows. Transpose the operands and call + InsertRows.*/ + matrix result; + TransposeMatrix(outer); + TransposeMatrix(inner); + result = InsertRows(outer, inner, start, mode); + TransposeMatrix(outer); + if (mode >= 0) TransposeMatrix(inner); + TransposeMatrix(&result); + return result; +} + +matrix InsertNullRows(matrix* m, int start, int rowsToAdd, int mode) +{ + matrix null; + if (! m) + { + merror(0, "InsertNewRows/COLUMNS: Null matrix pointer"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*Make sure the starting point is valid. Start will be the index of the first + of the new rows added. If index < 0, default to adding at the end of the + matrix.*/ + if (start < 0) start = NumberOfRows(*m); + if (start > NumberOfRows(*m)) + { + merror(0, "InsertNewRows/COLUMNS: First new index is out of range"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*Make sure the rowsToAdd is valid. Cannot be less than 1.*/ + if (rowsToAdd < 1) + { + merror(0, "InsertNewRows/COLUMNS: Rows/Columns to add is negative or zero"); + AllocateMatrix(&null, 0, 0); + return null; + } + if (mode >= 0) + { + return InsertNullRowsCopy(m, start, rowsToAdd, mode); + } + else + { + return InsertNullRowsOrig(m, start, rowsToAdd); + } +} + +matrix InsertNullColumns(matrix* m, int start, int colsToAdd, int mode) +{ + matrix result; + /*This is the column analogue of InsertNewRows. Transpose the matrix and call + InsertNewRows.*/ + TransposeMatrix(m); + result = InsertNullRows(m, start, colsToAdd, mode); + TransposeMatrix(&result); + TransposeMatrix(m); + return result; +} + +matrix RemoveRows(matrix* m, int start, int rowsToRemove, int mode) +{ + /*Matrix pointer cannot be null.*/ + matrix null; + if (! m) + { + merror(0, "REMOVEROWS/COLUMNS: Null matrix pointer"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*Start has to be the index of the first row to remove.*/ + if (start < 0 || start >= NumberOfRows(*m)) + { + merror(0, "REMOVEROWS/COLUMNS: Index of first row/column to remove is out of range"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*The row count cannot be less than 1, nor can it be so great that it + requires the removal of rows that do not exist.*/ + if (rowsToRemove < 1 || start + rowsToRemove > NumberOfRows(*m)) + { + merror(0, "REMOVEROWS/COLUMNS: Number of rows/columns to remove is out of range"); + AllocateMatrix(&null, 0, 0); + return null; + } + if (mode >= 0) + { + return RemoveRowsCopy(m, start, rowsToRemove, mode); + } + else + { + return RemoveRowsOrig(m, start, rowsToRemove); + } +} + +matrix RemoveColumns(matrix* m, int start, int colsToRemove, int Mode) +{ + matrix result; + /*This is the column analogue of RemoveRows. Transpose the matrix and call + RemoveRows.*/ + TransposeMatrix(m); + result = RemoveRows(m, start, colsToRemove, Mode); + TransposeMatrix(&result); + TransposeMatrix(m); + return result; +} + +matrix InsertRowsCopy(matrix* outer, matrix* inner, int start, int mode) +{ + matrix result; + /*Insert null rows.*/ + result = InsertNullRowsCopy(outer, start, NumberOfRows(*inner), mode); + /*Copy the inner matrix.*/ + CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, &result, start, 0); + return result; +} + +matrix InsertRowsOrig(matrix* outer, matrix* inner, int start) +{ + int i; + mtype **newAr; + /*If the outer and inner matrices are both type 2 untransposed, we can combine + memory directly. Otherwise we'll want to insert new blank rows into outer + and copy the contents of inner.*/ + if (outer->type == 2 && inner->type == 2 && !(outer->trans || inner->trans)) + { + /*Combine row memory directly.*/ + newAr = tcalloc(outer->nr + inner->nr, sizeof(mtype*)); + outer->nr += inner->nr; + for (i = 0; i < outer->nr; i++) + { + if (i < start) + { + newAr[i] = outer->ar[i]; + } + else if (i < start + inner->nr) + { + newAr[i] = inner->ar[i - start]; + } + else + { + newAr[i] = outer->ar[i - inner->nr]; + } + } + free(outer->ar); + free(inner->ar); + outer->ar = newAr; + memset(inner, 0, sizeof(matrix)); + } + else + { + /*Otherwise insert the new null rows and copy.*/ + InsertNullRowsOrig(outer, start, NumberOfRows(*inner)); + CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, outer, start, 0); + DeallocateMatrix(inner); + memset(inner, 0, sizeof(matrix)); + } + return *outer; +} + +matrix RemoveRowsCopy(matrix* m, int row, int rows, int mode) +{ + matrix result; + + /*Prepare the result matrix.*/ + if (mode) + { + AllocateMatrixType(mode, &result, NumberOfRows(*m) - rows, NumberOfColumns(*m)); + } + else + { + AllocateMatrix(&result, NumberOfRows(*m) - rows, NumberOfColumns(*m)); + } + /*Copy the first-half block.*/ + if (row) + { + CopyBlock(row, NumberOfColumns(*m), m, 0, 0, &result, 0, 0); + } + /*Copy the second-half block.*/ + if (NumberOfRows(*m) - row - rows) + { + CopyBlock(NumberOfRows(*m) - row - rows, NumberOfColumns(*m), m, row + rows, 0, &result, row, 0); + } + return result; +} + +matrix RemoveRowsOrig(matrix* m, int row, int rows) +{ + mtype** newAr; + int i; + /*Check to see if the remove can be optimized.*/ + if (m->type == 2 && (! m->trans)) + { + newAr = tcalloc(m->nr, sizeof(mtype*)); + for (i = 0; i < m->nr; i++) + { + if (i < row) + { + newAr[i] = m->ar[i]; + } + else if (i < row + rows) + { + free(m->ar[i]); + } + else + { + newAr[i - rows] = m->ar[i]; + } + } + free(m->ar); + m->ar = newAr; + m->nr -= rows; + } + else + { + /*If not, do a slow remove. This has to create a complete copy of the + matrix. Preserve matrix type.*/ + matrix old = *m; + *m = RemoveRowsCopy(m, row, rows, m->type); + DeallocateMatrix(&old); + } + return *m; +} + +matrix InsertNullRowsCopy(matrix *m, int row, int rows, int mode) +{ + matrix result; + /*Allocate the result matrix.*/ + if (mode) + { + AllocateMatrixType(mode, &result, NumberOfRows(*m) + rows, NumberOfColumns(*m)); + } + else + { + AllocateMatrix(&result, NumberOfRows(*m) + rows, NumberOfColumns(*m)); + } + /*Copy the first-half block.*/ + if (row) + { + CopyBlock(row, NumberOfColumns(*m), m, 0, 0, &result, 0, 0); + } + /*Copy the second-half block.*/ + if (NumberOfRows(*m) - row) + { + CopyBlock(NumberOfRows(*m) - row, NumberOfColumns(*m), m, row, 0, &result, row + rows, 0); + } + return result; +} + +matrix InsertNullRowsOrig(matrix *m, int row, int rows) +{ + mtype **newAr; + int i; + /*See if the insertion can be optimized.*/ + if (m->type == 2 && (! m->trans)) + { + m->nr += rows; + newAr = tcalloc(m->nr, sizeof(mtype*)); + for (i = 0; i < m->nr; i++) + { + if (i < row) + { + newAr[i] = m->ar[i]; + } + else if (i < row + rows) + { + newAr[i] = tcalloc(NumberOfColumns(*m), sizeof(mtype)); + } + else + { + newAr[i] = m->ar[i - rows]; + } + } + free(m->ar); + m->ar = newAr; + } + else + { + /*To insert blank rows we'll need to do a complete copy anyway.*/ + matrix old; + old = *m; + *m = InsertNullRowsCopy(m, row, rows, m->type); + DeallocateMatrix(&old); + } + return *m; +} Added: spnbox/extendedmatrix.h =================================================================== --- spnbox/extendedmatrix.h (rev 0) +++ spnbox/extendedmatrix.h 2009-07-14 15:31:42 UTC (rev 196) @@ -0,0 +1,86 @@ +#ifndef EXTENDEDMATRIX +#define EXTENDEDMATRIX + +matrix InsertRows(matrix* outer, matrix* inner, int start, int mode); +/*InsertRows inserts the rows of the matrix inner into the matrix outer in such +a way that the index of the first new row is start. If start is negative, the +new rows are added to the end of outer. +If mode is 0 or greater, InsertRows allocates a new matrix to hold the results +and leaves the operands unchanged. The type of the new matrix will be default +if mode is 0 or greater than 3, or the value of mode itself otherwise. +If mode is negative, then the matrix pointed to by outer is actually changed. +All the memory of inner is given to outer. Note that this means that inner +should not ever be deallocated; to deallocate it will deallocate part of the +memory used by the modified outer. +If in modification mode, InsertRows can optimize the operation if both matrices +are type 2 untransposed. The optimization reduces computational complexity by +a factor at least equal to the number of columns in the matrices.*/ + +matrix InsertColumns(matrix* outer, matrix* inner, int start, int mode); +/*InsertColumns inserts the columns of the matrix inner into the matrix outer in +such a way that the index of the first new column is start. If start is negative, +the new columns are added to the end of outer. +If mode is 0 or greater, InsertColumns allocates a new matrix to hold the results +and leaves the operands unchanged. The type of the new matrix will be default +if mode is 0 or greater than 3, or the value of mode itself otherwise. +If mode is negative, then the matrix pointed to by outer is actually changed. +All the memory of inner is given to outer. Note that this means that inner +should not ever be deallocated; to deallocate it will deallocate part of the +memory used by the modified outer. +If in modification mode, InsertColumns can optimize the operation if both +matrices are type 2 transposed. The optimization reduces computational +complexity by a factor at least equal to the number of rows in the matrices.*/ + +matrix InsertNullRows(matrix* m, int start, int rowsToAdd, int mode); +/*InsertNewRows adds one or more new null (all-zero) rows into the given matrix. +start The index of the first of the new rows. If it is set to a negative + number, InsertNewRows adds the block of rows to the bottom of the matrix. + If it is too high the function will show an error message and + terminate execution. +rowsToAdd The number of rows to add to the matrix. Rows will be added in a + contiguous block. +mode If mode is 0 or greater than 3, a new matrix of the default type + will be allocated to hold the results and the operand will remain + unchanged. If mode is 1, 2, or 3, the new matrix will be of type + 1, 2, or 3. If mode is less than zero, the new rows will be + inserted into the original matrix pointed to by m. +The return value is the result matrix. +Note that in modification mode, if the matrix is a type-2 un-transposed, +InsertNewRows is able to invoke a special highly-optimized algorithm that reduces +the computational complexity of the operation by at least a factor corresponding +to the number of columns in the matrix.*/ + +matrix InsertNullColumns(matrix* m, int start, int colsToAdd, int mode); +/*InsertNewColumns adds one or more new (all-zero) rows into the given matrix. +See InsertNewRows; the parameters of InsertNewColumns are the column analogues of +InsertNewRows' parameters. The return value is the new matrix. InsertNewColumns +can apply the same type of optimization, except that it will work only for +transposed type-2 matrices and the factor of optimization is at least equal to +number of rows in the matrices.*/ + +matrix RemoveRows(matrix* m, int start, int rowsToRemove, int mode); +/*RemoveRows removes one or more contiguous rows from the given matrix. +start The index of the first row to remove. If it is out of range the + function will fail with an error message. +rowsToRemove The number of rows to remove. If the number is less than 1 or + large enough that it would attempt to remove nonexistant rows, + the function fails with an error message and terminates execution. +mode If mode is 0 or greater than 3, a new matrix of the default type + will be allocated to hold the results and the operand will remain + unchanged. If mode is 1, 2, or 3, the new matrix will be of type + 1, 2, or 3. If mode is less than zero, the rows will be removed + from the original matrix pointed to by m. +The return value is the new matrix. +If RemoveRows is passed a type-2 untransposed matrix in modification mode ( +modifying the original matrix), it employs optimization that reduces the +computational complexity of the operation by at approximately a factor +corresponding to the number of columns in the matrix.*/ + +matrix RemoveColumns(matrix* m, int start, int colsToRemove, int mode); +/*RemoveColumns removes one or more contiguous columns from the given matrix. +See RemoveRows; the parameters of RemoveColumns are the column analogues of +RemoveRows. The return value is the new matrix. +RemoveColumns is able to employ the same type of optimization as RemoveRows +(reducing computational complexity by a factor at least equal to the number of +rows in the matrix) if and only if the matrix is a type-2 transposed.*/ +#endif Modified: spnbox/matrixmath.c =================================================================== --- spnbox/matrixmath.c 2009-07-13 18:01:14 UTC (rev 195) +++ spnbox/matrixmath.c 2009-07-14 15:31:42 UTC (rev 196) @@ -2,12 +2,50 @@ matrixmath.c Written in 2009 by Stephen Camp Updated 19 May 2009 +Updated 13 July 2009 ****************************************************************************/ #include "../pnheaders/general.h" #include "../pnheaders/matrix.h" #include "matrixmath.h" +/*This function is an internal function used by many of the matrixmath functions. +It examines the dst pointer to determine if it points to a valid destination +or if it requests a destination be allocated. +If the former, the function checks to make sure the destination is of the +correct size. If the latter, it does the allocation..*/ +static int CheckDestination(matrix** dst, int dstRows, int dstCols, matrix* local) +{ + /*If *dst > 3 it is a valid pointer. Check to make sure the destination has + the requested size.*/ + if ((long) *dst > 3) + { + if (NumberOfRows(**dst) != dstRows || NumberOfColumns(**dst) != dstCols) + { + return 0; + } + else + { + /*Return 1. This will indicate success with no allocation.*/ + return 1; + } + } + /*If a specific type of allocation is is requested...*/ + else if (*dst) + { + AllocateMatrixType((int) *dst, local, dstRows, dstCols); + *dst = local; + } + /*Otherwise, use the default allocated type.*/ + else + { + AllocateMatrix(local, dstRows, dstCols); + *dst = local; + } + /*Return -1. This will indicate success with allocation.*/ + return -1; +} + /*This function transposes the matrix passed in Matrix. Currently, this operation is very fast as it consists only of changing an internal flag in the matrix structure.*/ @@ -23,18 +61,15 @@ int i, j, rows, cols; /*This will hold an empty matrix for error return or be allocated to be the destination matrix.*/ - matrix destinationMatrix; - //This will point to the final destination matrix. - matrix *destination; - + matrix local; //Zero the destination matrix to use as an error return value. - AllocateMatrix(&destinationMatrix, 0, 0); + AllocateMatrix(&local, 0, 0); //Check to make sure none of the parameters are null. if(! (addA && addB)) { merror(0, "AddMatrix: One of the parameters is a null pointer"); - return destinationMatrix; + return local; } //Check to make sure the matrices are of the same dimension. rows = NumberOfRows(*addA); @@ -43,45 +78,25 @@ if (rows != NumberOfRows(*addB) || cols != NumberOfColumns(*addB)) { merror(0, "AddMatrix: The operands do not have the same dimensions"); - return destinationMatrix; + return local; } //Arrange the destination matrix. - if (! dst) + if (! CheckDestination(&dst, rows, cols, &local)) { - //If dst is a null pointer, allocate a new matrix of the default type. - AllocateMatrix(&destinationMatrix, rows, cols); - destination = &destinationMatrix; + merror(0, "AddMatrix: The destination matrix is the wrong size"); + return local; } - else if ((int) dst < 4) - { - /*If dst is between 1 and 3, treat it as the type number of a new matrix of - a specific type to hold the destination.*/ - AllocateMatrixType((int) dst, &destinationMatrix, rows, cols); - destination = &destinationMatrix; - } - else - { - /*Otherwise assume dst is a valid pointer to a pre-allocated matrix. Make - sure the dimensions are right. Make sure the destination matrix has the - right dimensions.*/ - if (rows != NumberOfRows(*dst) || cols != NumberOfColumns(*dst)) - { - merror(0, "AddMatrix: The destination matrix has the wrong dimensions"); - return destinationMatrix; - } - destination = dst; - } //Add the matrices for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { - SetMatrixEl(destination, i, j, GetMatrixEl(addA, i, j) + GetMatrixEl(addB, i, j)); + SetMatrixEl(dst, i, j, GetMatrixEl(addA, i, j) + GetMatrixEl(addB, i, j)); } } - return *destination; + return *dst; } /* SubtractMatrix does an element-by-element subtraction. The elements of the @@ -92,17 +107,15 @@ int i, j, rows, cols; /*This will hold an empty matrix for error return or be allocated to be the destination matrix.*/ - matrix destinationMatrix; - /*This will point to the final destination matrix.*/ - matrix *destination; + matrix local; //Zero the destination matrix to use as an error return value. - AllocateMatrix(&destinationMatrix, 0, 0); + AllocateMatrix(&local, 0, 0); if(! (add && sub)) { merror(0, "SubtractMatrix: One of the operands is a null pointer"); - return; + return local; } //Check to make sure the matrices are of the same dimension. rows = NumberOfRows(*add); @@ -111,43 +124,23 @@ if (rows != NumberOfRows(*sub) || cols != NumberOfColumns(*sub)) { merror(0, "SubtractMatrix: The operands do not have the same dimensions"); - return; + return local; } //Arrange the destination matrix. - if (! dst) + if (! CheckDestination(&dst, rows, cols, &local)) { - //If dst is a null pointer, allocate a new matrix of the default type. - AllocateMatrix(&destinationMatrix, rows, cols); - destination = &destinationMatrix; + merror(0, "SubtractMatrix: The destination matrix has the wrong dimensions"); + return local; } - else if ((int) dst < 4) - { - /*If dst is between 1 and 3, treat it as the type number of a new matrix of - a specific type to hold the destination.*/ - AllocateMatrixType((int) dst, &destinationMatrix, rows, cols); - destination = &destinationMatrix; - } - else - { - /*Otherwise assume dst is a valid pointer to a pre-allocated matrix. Make - sure the dimensions are right.*/ - //Make sure the destination matrix has the right dimensions. - if (rows != NumberOfRows(*dst) || cols != NumberOfColumns(*dst)) - { - merror(0, "SubtractMatrix: The destination matrix has the wrong dimensions"); - return destinationMatrix; - } - destination = dst; - } //Subtract the matrices for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { - SetMatrixEl(destination, i, j, GetMatrixEl(add, i, j) - GetMatrixEl(sub, i, j)); + SetMatrixEl(dst, i, j, GetMatrixEl(add, i, j) - GetMatrixEl(sub, i, j)); } } - return *destination; + return *dst; } /*MultiplyMatrix does a matrix multiplication of the matrices pointed to by @@ -157,12 +150,10 @@ int i, j, k, rows, cols, inner, currentsum; /*This will hold an empty matrix for error return or be allocated to be the destination matrix.*/ - matrix destinationMatrix; - //This will point to the final destination matrix. - matrix *destination; + matrix local; //Zero the destination matrix to use as an error return value. - AllocateMatrix(&destinationMatrix, 0, 0); + AllocateMatrix(&local, 0, 0); //Check to make sure none of the operands are null. if(! (left && right)) @@ -183,35 +174,15 @@ if (inner != NumberOfRows(*right)) { merror(0, "MultiplyMatrix: The matrices do not have matching inner dimensions"); - return; + return local; } //Arrange the destination matrix. - if (! dst) + if (! CheckDestination(&dst, rows, cols, &local)) { - //If dst is a null pointer, allocate a new matrix of the default type. - AllocateMatrix(&destinationMatrix, rows, cols); - destination = &destinationMatrix; + merror(0, "MultiplyMatrix: The destination matrix has the wrong dimensions"); + return local; } - else if ((int) dst < 4) - { - /*If dst is between 1 and 3, treat it as the type number of a new matrix of - a specific type to hold the destination.*/ - AllocateMatrixType((int) dst, &destinationMatrix, rows, cols); - destination = &destinationMatrix; - } - else - { - /*Otherwise assume dst is a valid pointer to a pre-allocated matrix. Make - sure the dimensions are right. Make sure the destination matrix has the - right dimensions.*/ - if (rows != NumberOfRows(*dst) || cols != NumberOfColumns(*dst)) - { - merror(0, "MultiplyMatrix: The destination matrix has the wrong dimensions"); - return destinationMatrix; - } - destination = dst; - } /*Now, take the matrix product. Each element of the destination is the sum of corresponding elements of *left by row and *right by column.*/ @@ -224,15 +195,20 @@ { currentsum += (GetMatrixEl(left, i, k) * GetMatrixEl(right, k, j)); } - SetMatrixEl(destination, i, j, currentsum); + SetMatrixEl(dst, i, j, currentsum); } } - return *destination; + return *dst; } void ShowMatrix(const matrix* m, const char* title) { int i, j; + if (! m) + { + printf ("Matrix $s (null pointer).\n", title); + return; + } printf("Matrix %s (%d x %d of type %d):\n", title, NumberOfRows(*m), NumberOfColumns(*m), m->type); for (i = 0; i < NumberOfRows(*m); i++) { @@ -244,98 +220,6 @@ } } -matrix InsertRows(matrix* outer, matrix* inner, int start, matrix* dst) -{ - matrix* destination; - matrix destinationMatrix; - /*Zero destinationMatrix so that it can be used as an error return value.*/ - AllocateMatrix(&destinationMatrix, 0, 0); - - /*Check parameters. None of the pointers can be null except dst.*/ - if(! (outer && inner)) - { - merror(0, "InsertRows/Columns: One of the operands is a null pointer"); - return destinationMatrix; - } - /*inner and outer must have the same number of columns.*/ - if (NumberOfColumns(*inner) != NumberOfColumns(*outer)) - { - merror(0, "InsertRows/Columns: The operands do not have the same number of columns/rows"); - return destinationMatrix; - } - - /*If start is negative, default to adding to the end.*/ - if (start < 0) start = NumberOfRows(*outer); - /*start cannot point to a row farther out than the first possible new row*/ - if (start > NumberOfRows(*outer)) - { - merror(0, "InsertRows/Columns: The index of the first inserted row/column is out of range"); - return destinationMatrix; - } - - /*Check to see if dst has been allocated or is a number indicated the matrix - type the user wants allocated for the result.*/ - if (! dst) - { - /*If the dst pointer is null, allocate a new matrix of the default type and - use this as the destination matrix.*/ - AllocateMatrix(&destinationMatrix, NumberOfRows(*inner) + NumberOfRows(*outer), NumberOfColumns(*inner)); - destination = &destinationMatrix; - } - else if((int) dst < 4) - { - /*If the dst pointer is between 1 and 3, treat it like an integer describing - the type of the desired destination matrix.*/ - AllocateMatrixType((int) dst, &destinationMatrix, NumberOfRows(*inner) + NumberOfRows(*outer), NumberOfColumns(*inner)); - destination = &destinationMatrix; - } - else - { - /*Assume dst is a valid address. Check to make sure it has the right - dimensions.*/ - destination = dst; - if (! (NumberOfRows(*inner) + NumberOfRows(*outer) == NumberOfRows(*dst) && NumberOfColumns(*inner) == NumberOfColumns(*dst))) - { - merror(0, "InsertRows/Columns: The destination matrix does not have the proper dimensions."); - return destinationMatrix; - } - } - - /*Copy the beforehand part of the outer matrix.*/ - if (start) - { - CopyBlock(start, NumberOfColumns(*outer), outer, 0, 0, destination, 0, 0); - } - - /*Copy the inner matrix.*/ - CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, destination, start, 0); - - /*Copy the final part of the outer matrix.*/ - if (NumberOfRows(*outer) - start) - { - CopyBlock(NumberOfRows(*outer) - start, NumberOfColumns(*outer), outer, start, 0, destination, start + NumberOfRows(*inner), 0); - } - - /*Return the final result.*/ - return (*destination); -} - -matrix InsertColumns(matrix* outer, matrix* inner, int start, matrix* dst) -{ - /*This is the column analogue of InsertRows. Transpose the operands and call - InsertRows.*/ - matrix result; - TransposeMatrix(outer); - TransposeMatrix(inner); - if ((int) dst > 3) TransposeMatrix(dst); - result = InsertRows(outer, inner, start, dst); - TransposeMatrix(outer); - TransposeMatrix(inner); - TransposeMatrix(&result); - if ((int) dst > 3) TransposeMatrix(dst); - return result; -} - /*This function multiplies a particular row of the left matrix by a particular column of the right matrix. If the row or column index is a negative constaint, the pointer to the corresponding matrix is interpreted as a pointer to an array @@ -410,309 +294,3 @@ } return 1; } - -/*This function is called by InsertNewRows and InsertNewColumns when they detect that the -matrix is properly formatted for optimized row/column add. It assumes that -basic parameter checking has been done by AddRow and AddCol. It is a private -function internal to this file.*/ -static void AddRowsFast(matrix* m, int start, int rowsToAdd) -{ - int i; - mtype** NewAr; - m->nr += rowsToAdd; - NewAr = tcalloc(m->nr, sizeof(mtype*)); - for (i = 0; i < m->nr; i++) - { - /*If we have not yet reached the insertion point, copy addresses directly.*/ - if (i < start) - { - NewAr[i] = m->ar[i]; - } - /*At the insertion point, allocate space for a new row.*/ - else if (i < start + rowsToAdd) - { - NewAr[i] = tcalloc(m->nc, sizeof(mtype)); - } - /*After the insertion point, each new array element should get the value - of the previous element in the original array.*/ - else - { - NewAr[i] = m->ar[i - rowsToAdd]; - } - } - /*Free and reassign memory.*/ - free(m->ar); - m->ar = NewAr; -} - -/*This function is called by InsertNewRows and InsertNewColumns when they detect that a -matrix is not properly formatted for fast row add. It is a private function -internal to this file.*/ -static void AddRowsSlow(matrix* m, int start, int rowsToAdd) -{ - int i; - matrix NewM; - - /*Preserve the transpose state of the matrix.*/ - if (m->trans) - { - AllocateMatrixType(m->type, &NewM, NumberOfColumns(*m), NumberOfRows(*m) + rowsToAdd); - TransposeMatrix(&NewM); - } - else - { - AllocateMatrixType(m->type, &NewM, NumberOfRows(*m) + rowsToAdd, NumberOfColumns(*m)); - } - - for (i = 0; i < NumberOfRows(NewM); i++) - { - if (i < start) - { - CopyBlock(1, NumberOfColumns(NewM), m, i, 0, &NewM, i, 0); - } - else if (i >= start + rowsToAdd) - { - CopyBlock(1, NumberOfColumns(NewM), m, i - rowsToAdd, 0, &NewM, i, 0); - } - } - DeallocateMatrix(m); - (*m) = NewM; -} - -/*This function is called by RemoveRow and RemoveCol when they detect that the -matrix is properly formatted for an optimized row/column removal. It assumes -that basic parameter checking has been done by AddRow and AddCol. It is a -private function internal to this file.*/ -static void RemoveRowsFast(matrix* m, int start, int rowsToAdd) -{ - int i; - mtype** NewAr; - NewAr = tcalloc(m->nr, sizeof(mtype*)); - for (i = 0; i < m->nr; i++) - { - if (i < start) - { - NewAr[i] = m->ar[i]; - } - else if (i < start + rowsToAdd) - { - free(m->ar[i]); - } - else - { - NewAr[i - rowsToAdd] = m->ar[i]; - } - } - free(m->ar); - m->ar = NewAr; - m->nr -= rowsToAdd; -} - -/*This function is called by RemoveRows and RemoveColumns when they detect that -a matrix is not properly formatted for fast row removal. It is a private -function internal to this file.*/ -static int RemoveRowsSlow(matrix *m, int start, int rowsToRemove) -{ - int i; - matrix NewM; - /*Preserve the transpose state of the matrix.*/ - if (m->trans) - { - AllocateMatrixType(m->type, &NewM, NumberOfColumns(*m), NumberOfRows(*m) - rowsToRemove); - TransposeMatrix(&NewM); - } - else - { - AllocateMatrixType(m->type, &NewM, NumberOfRows(*m) - rowsToRemove, NumberOfColumns(*m)); - } - for (i = 0; i < NumberOfRows(NewM); i++) - { - if (i < start) - { - CopyBlock(1, NumberOfColumns(NewM), m, i, 0, &NewM, i, 0); - } - else - { - CopyBlock(1, NumberOfColumns(NewM), m, i + rowsToRemove, 0, &NewM, i, 0); - } - } - DeallocateMatrix(m); - *m = NewM; -} - -int InsertNewRows(matrix* m, int start, int rowsToAdd) -{ - int i; - matrix NewM; - if (! m) - { - merror(0, "InsertNewRows/COLUMNS: Null matrix pointer"); - return 0; - } - /*Make sure the starting point is valid. Start will be the index of the first - of the new rows added. If index < 0, default to adding at the end of the - matrix.*/ - if (start < 0) start = NumberOfRows(*m); - if (start > NumberOfRows(*m)) - { - merror(0, "InsertNewRows/COLUMNS: First new index is out of range"); - return 0; - } - /*Make sure the rowsToAdd is valid. Cannot be less than 1.*/ - if (rowsToAdd < 1) - { - merror(0, "InsertNewRows/COLUMNS: Rows/Columns to add is negative or zero"); - return 0; - } - - if (m->type == 2 && (! m->trans)) - { - /*If matrix is an untransposed type 2, the row add can be heavily - optimized.*/ - AddRowsFast(m, start, rowsToAdd); - } - else - { - AddRowsSlow(m, start, rowsToAdd); - return 1; - } -} - -int InsertNewColumns(matrix* m, int start, int colsToAdd) -{ - int result; - /*This is the column analogue of InsertNewRows. Transpose the matrix and call - InsertNewRows.*/ - TransposeMatrix(m); - result = InsertNewRows(m, start, colsToAdd); - TransposeMatrix(m); - return result; -} - -int RemoveRows(matrix* m, int start, int rowsToRemove) -{ - /*Matrix pointer cannot be null.*/ - if (! m) - { - merror(0, "REMOVEROWS/COLUMNS: Null matrix pointer"); - return 0; - } - /*Start has to be the index of the first row to remove.*/ - if (start < 0 || start >= NumberOfRows(*m)) - { - merror(0, "REMOVEROWS/COLUMNS: Index of first row/column to remove is out of range"); - return 0; - } - /*The row count cannot be less than 1, nor can it be so great that it - requires the removal of rows that do not exist.*/ - if (rowsToRemove < 1 || start + rowsToRemove > NumberOfRows(*m)) - { - merror(0, "REMOVEROWS/COLUMNS: Number of rows/columns to remove is out of range"); - return 0; - } - /*See if we can optimize the removal.*/ - if (m->type == 2 && ! m->trans) - { - RemoveRowsFast(m, start, rowsToRemove); - } - else - { - RemoveRowsSlow(m, start, rowsToRemove); - } - return 1; -} - -int RemoveColumns(matrix* m, int start, int colsToRemove) -{ - int result; - /*This is the column analogue of RemoveRows. Transpose the matrix and call - RemoveRows.*/ - TransposeMatrix(m); - result = RemoveRows(m, start, colsToRemove); - TransposeMatrix(m); - return result; -} - -static void MergeRowsFast(matrix *outer, matrix *inner, int start) -{ - int i; - mtype **newAr; - - newAr = tcalloc(outer->nr + inner->nr, sizeof(mtype*)); - outer->nr += inner->nr; - for (i = 0; i < outer->nr; i++) - { - if (i < start) - { - newAr[i] = outer->ar[i]; - } - else if (i < start + inner->nr) - { - newAr[i] = inner->ar[i - start]; - } - else - { - newAr[i] = outer->ar[i - inner->nr]; - } - } - free(outer->ar); - free(inner->ar); - outer->ar = newAr; - memset(inner, 0, sizeof(matrix)); -} - -int MergeRows(matrix *outer, matrix *inner, int start) -{ - /*Neither of the matrices can be null pointers.*/ - if (! (inner && outer)) - { - merror(0, "MERGEROWS/COLUMNS: Null matrix pointer"); - return 0; - } - /*If start is negative, default to adding rows at the end.*/ - if (start < 0) start = NumberOfRows(*outer); - /*We cannot add rows any farther out than the end.*/ - if (start > NumberOfRows(*outer)) - { - merror(0, "MERGEROWS/COLUMNS: Start index is out of range"); - return 0; - } - /*The matrices must have the same number of columns.*/ - if (NumberOfColumns(*outer) != NumberOfColumns(*inner)) - { - merror(0, "MERGEROWS/COLUMNS: The outer and inner matrices do not have the same number of columns"); - return 0; - } - /*Attempt to optimize.*/ - if (outer->type == 2 && inner->type == 2 && ! (outer->trans || inner->trans)) - { - MergeRowsFast(outer, inner, start); - } - else - { - /*Otherwise, do a slow add and copy.*/ - InsertNewRows(outer, start, NumberOfRows(*inner)); - CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, outer, start, 0); - /*For consistencies' sake (with Fast Row Merge), deallocate the inner matrix - and zero it.*/ - DeallocateMatrix(inner); - memset(inner, 0, sizeof(matrix)); - } - return 1; -} - -int MergeColumns(matrix *outer, matrix *inner, int start) -{ - /*This is the column analogue of MergeRows. Simply transpose the operands and - call MergeRows.*/ - int result; - TransposeMatrix(outer); - TransposeMatrix(inner); - result = MergeRows(outer, inner, start); - TransposeMatrix(outer); - TransposeMatrix(inner); - return result; -} - - - Modified: spnbox/matrixmath.h =================================================================== --- spnbox/matrixmath.h 2009-07-13 18:01:14 UTC (rev 195) +++ spnbox/matrixmath.h 2009-07-14 15:31:42 UTC (rev 196) @@ -42,25 +42,6 @@ /*ShowMatrix is a debugging function that dumps the contents of a matrix to the screen in a human-readable format.*/ -matrix InsertRows(matrix* outer, matrix* inner, int start, matrix* dst); -/*InsertRows returns a matrix that is a copy of outer with the rows of inner -inserted in such a way that the first of the inserted rows has index start. If -start is negative, the inserted rows are added at the end of the matrix. -If dst is a valid pointer the matrix to which it points is used as the -destination. If dst is null, the function allocates a new matrix of the type -determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, -the function allocates a new matrix of that type number.*/ - -matrix InsertColumns(matrix* outer, matrix* inner, int start, matrix* dst); -/*InsertColumns returns a matrix that is a copy of outer with the columns of -inner inserted in such a way that the first of the inserted columns has index -start. If start is negative, the inserted columns are added at the end of the -matrix. -If dst is a valid pointer the matrix to which it points is used as the -destination. If dst is null, the function allocates a new matrix of the type -determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, -the function allocates a new matrix of that type number.*/ - int MultiplyVector(matrix* left, matrix* right, int Row, int Col, int Length); /*This function multiplies a particular row of the left matrix by a particular column of the right matrix. If the row or column index is a negative constaint, @@ -72,70 +53,6 @@ /*MatrixEqualMatrix tests the equality of matrices A and B. It returns nonzero if the matrices are equal and zero if they are different.*/ -int InsertNewRows(matrix* m, int start, int rowsToAdd); -/*InsertNewRows adds one or more contiguous rows to the given matrix. -start The index of the first of the new rows. If it is set to a negative - number, InsertNewRows adds the block of rows to the bottom of the matrix. - If it is too high the function will show an error message and - terminate execution. -rowsToAdd The number of rows to add to the matrix. Rows will be added in a - contiguous block. -Return value is nonzero on success and zero on failure. -Note that if the matrix is a type-2 un-transposed, InsertNewRows is able to invoke -a special highly-optimized algorithm that reduces the computational complexity -of the operation by at least a factor corresponding to the number of columns in -the matrix.*/ - -int InsertNewColumns(matrix* m, int start, int colsToAdd); -/*InsertNewColumns adds one or more contiguous columns to the given matrix. See -InsertNewRows; the parameters of InsertNewColumns are the column analogues of InsertNewRows' -parameters. The return value is nonzero on success and zero on failure. -InsertNewColumns is able to employ the same type of optimization as InsertNewRows (decreasing -computational complexity by a factor at least equal to the number of rows in the -matrix) if and only if the matrix is a type-2 transposed.*/ - -int RemoveRows(matrix* m, int start, int rowsToRemove); -/*RemoveRows removes one or more contiguous rows from the given matrix. -start The index of the first row to remove. If it is out of range the - function will fail with an error message. -rowsToRemove The number of rows to remove. If the number is less than 1 or - large enough that it would attempt to remove nonexistant rows, - the function fails with an error message and terminates execution. -The return value is nonzero on success and zero on failure. -If RemoveRows is passed a type-2 untransposed matrix, it employs optimization -that reduces the computational complexity of the operation by at approximately a -factor corresponding to the number of columns in the matrix.*/ - -int RemoveColumns(matrix* m, int start, int colsToRemove); -/*RemoveColumns removes one or more contiguous columns from the given matrix. -See RemoveRows; the parameters of RemoveColumns are the column analogues of -RemoveRows. The return value is nonzero on success and zero on failure. -RemoveColumns is able to employ the same type of optimization as RemoveRows -(reducing computational complexity by a factor at least equal to the number of -rows in the matrix) if and only if the matrix is a type-2 transposed.*/ - -int MergeRows(matrix *outer, matrix *inner, int start); -/*MergeRows inserts the rows of the inner matrix into the outer matrix -in such a way that the first of the inserted rows has the specified start index. -Note that the function actually modifies both of the operands; it modifies the -contents of the matrix pointed to by outer by inserting the new rows, and after -inserted deallocates and zeroes the matrix pointed to by inner. The return value -is nonzero on success and zero on failure. -If both the operand matrices are type 2 untransposed, MergeRows will will employ -an optimization that will decrease computational complexity by a factor at least -equal to the number of columns in the matrices.*/ - -int MergeColumns(matrix *outer, matrix *inner, int start); -/*MergeColumns inserts the columns of the inner matrix into the outer matrix -in such a way that the first of the inserted columns has the specified start -index. Note that the function actually modifies both of the operands; it -modifies the contents of the matrix pointed to by outer by inserting the new -columns, and after inserted deallocates and zeroes the matrix pointed to by -inner. The return value is nonzero on success and zero on failure. -If both the operand matrices are type 2 transposed, MergeColumns will will -employ an optimization that will decrease computational complexity by a factor -at least equal to the number of rows in the matrices.*/ - #endif Modified: spnbox/supervis.c =================================================================== --- spnbox/supervis.c 2009-07-13 18:01:14 UTC (rev 195) +++ spnbox/supervis.c 2009-07-14 15:31:42 UTC (rev 196) @@ -1,6 +1,7 @@ #include "spnbox.h" #include "../pnheaders/matrix.h" #include "matrixmath.h" +#include "extendedmatrix.h" supervis_r supervis(matrix* PlantIn, matrix* PlantOut, matrix* L) { @@ -91,11 +92,11 @@ /*Add the rows of the supervisor to the end of the net matrices. The result should be stored in a type-2 matrix.*/ - toReturn.Dfm = InsertRows(PlantOut, &supervisorDm, -1, (matrix*) 2); + toReturn.Dfm = InsertRows(PlantOut, &supervisorDm, -1, 2); /*Concatenate the columns of the input matrices. The result should be stored in a type-2 matrix.*/ - toReturn.Dfp = InsertRows(PlantIn, &supervisorDp, -1, (matrix*) 2); + toReturn.Dfp = InsertRows(PlantIn, &supervisorDp, -1, 2); /*Free any memory that was allocated. If we allocated new space for constraints, then a new matrix was allocated for it*/ Modified: spnbox/tests/Makefile =================================================================== --- spnbox/tests/Makefile 2009-07-13 18:01:14 UTC (rev 195) +++ spnbox/tests/Makefile 2009-07-14 15:31:42 UTC (rev 196) @@ -10,13 +10,14 @@ COMMON=StructuredIO.o test.o MemoryManager.o general.o pns.o matrix.o matrixmath.o deallocation.o #These symbols define the dependencies of various test executables. +EXTENDEDMATRIX=extendedmatrix.o IPSLV=ipslv.o ../liblpsolve55.a IPSOLVE=ipsolve.o $(IPSLV) ISADM=isadm.o ISSIPH=issiph.o MSPLIT=msplit.o PN2ACPN=pn2acpn.o -SUPERVIS=supervis.o +SUPERVIS=supervis.o $(EXTENDEDMATRIX.O) ACTN=actn.o $(NLTRANS) ILPADM=ilpadm.o $(IPSOLVE) LINENF=linenf.o $(ILPADM) @@ -29,7 +30,9 @@ COMMONHEADER=../spnbox.h test.h ../../pnheaders/pns.h ../../pnheaders/matrix.h ../matrixmath.h ../MemoryManager.h StructuredIO.h #Targets -all: ipslv ipsolve isadm issiph msplit pn2acpn supervis actn ilpadm linenf nltrans pn2eacpn reduce tactn +all: extendedmatrix ipslv ipsolve isadm issiph msplit matrixmath pn2acpn supervis actn ilpadm linenf nltrans pn2eacpn reduce tactn +extendedmatrix: test-extendedmatrix.o $(EXTENDEDMATRIX) $(COMMON) + $(COMPILER) -o extendedmatrix.exe test-extendedmatrix.o $(EXTENDEDMATRIX) $(COMMON) ipslv: test-ipslv.o $(IPSLV) $(COMPILER) -o ipslv.exe test-ipslv.o $(IPSLV) ipsolve: test-ipsolve.o $(COMMON) $(IPSOLVE) @@ -44,8 +47,8 @@ $(COMPILER) -o matrixmath.exe test-matrixmath.o $(COMMON) pn2acpn: test-pn2acpn.o $(COMMON) $(PN2ACPN) $(COMPILER) -o pn2acpn.exe test-pn2acpn.o $(COMMON) $(PN2ACPN) -supervis: test-supervis.o $(COMMON) $(SUPERVIS) - $(COMPILER) -o supervis.exe test-supervis.o $(COMMON) $(SUPERVIS) +supervis: test-supervis.o $(COMMON) $(EXTENDEDMATRIX) $(SUPERVIS) + $(COMPILER) -o supervis.exe test-supervis.o $(COMMON) $(EXTENDEDMATRIX) $(SUPERVIS) actn: test-actn.o $(COMMON) $(ACTN) $(COMPILER) -o actn.exe test-actn.o $(COMMON) $(ACTN) ilpadm: test-ilpadm.o $(COMMON) $(ILPADM) @@ -72,6 +75,8 @@ $(COMPILER) -c ../chkcons.c deallocation.o: ../deallocation.c ../spnbox.h $(COMPILER) -c ../deallocation.c +extendedmatrix.o: ../extendedmatrix.c ../extendedmatrix.h ../../pnheaders/matrix.h ../../pnheaders/general.h + $(COMPILER) -c ../extendedmatrix.c general.o: ../../pnheaders/general.c ../../pnheaders/general.h $(COMPILER) -c ../../pnheaders/general.c ilpadm.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../ilpadm.c @@ -104,7 +109,7 @@ $(COMPILER) -c ../../pnheaders/pns.c reduce.o: ../spnbox.h ../../pnheaders/matrix.h ../reduce.c $(COMPILER) -c ../reduce.c -supervis.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/ ../../pnheaders/matrix.h ../supervis.c +supervis.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/ ../../pnheaders/matrix.h ../supervis.c ../extendedmatrix.h $(COMPILER) -c ../supervis.c StructuredIO.o: ../MemoryManager.h ../../pnheaders/matrix.h StructuredIO.h StructuredIO.c $(COMPILER) -c StructuredIO.c @@ -116,6 +121,8 @@ #Rules for making the test executable object files. test-actn.o: test-actn.c $(COMMONHEADER) $(COMPILER) -c test-actn.c +test-extendedmatrix.o: test-extendedmatrix.c $(COMMONHEADER) + $(COMPILER) -c test-extendedmatrix.c test-ilpadm.o: test-ilpadm.c $(COMMONHEADER) $(COMPILER) -c test-ilpadm.c test-ipslv.o: test-ipslv.c Added: spnbox/tests/test-extendedmatrix.c =================================================================== --- spnbox/tests/test-extendedmatrix.c (rev 0) +++ spnbox/tests/test-extendedmatrix.c 2009-07-14 15:31:42 UTC (rev 196) @@ -0,0 +1,494 @@ +#include <time.h> +#include "test.h" +#include "../extendedmatrix.h" + +#define FF_OPTIMIZATION 0 +#define FF_OPERATION 1 +#define FF_MODE 2 +#define FF_A 3 +#define FF_B 4 +#define FF_ROW 5 +#define FF_COL 6 +#define FF_ROWS 7 +#define FF_COLS 8 +#define FF_REPS 9 +#define FF_SIZE 10 +#define FF_SPEEDTEST 11 + +static void SInsertR(int Size, int Reps, int Row, int Rows, int Optimized); +static void SInsertC(int Size, int Reps, int Col, int Cols, int Optimized); +static void TInsertR(matrix *A, matrix *B, int Row, int Mode, int Optimized); +static void TInsertC(matrix *A, matrix *B, int Col, int Mode, int Optimized); +static void SRemoveR(int Size, int Reps, int Row, int Rows, int Optimized); +static void SRemoveC(int Size, int Reps, int Col, int Cols, int Optimized); +static void TRemoveR(matrix *A, int Row, int Rows, int Mode, int Optimized); +static void TRemoveC(matrix *A, int Col, int Cols, int Mode, int Optimized); +static void SInsertNullR(int Size, int Reps, int Row, int Rows, int Optimized); +static void SInsertNullC(int Size, int Reps, int Col, int Cols, int Optimized); +static void TInsertNullR(matrix *A, int Row, int Rows, int Mode, int Optimized); +static void TInsertNullC(matrix *A, int Col, int Cols, int Mode, int Optimized); + +static void PrintPercent(int num, int denom); +static matrix* AllocateMatrices(int rows, int cols, int Reps, int Transpose); +static void DeallocateMatrices(int reps, matrix *m); +void SetDefaults(char* optimization, char* Operation, int *Mode, matrix *A, matrix *B, int *Row, int *Column, int* Rows, int *Columns, int *Reps, int *Size, char *speedtest); + +int main(int argc, char* argv[]) +{ + FILE* input; + + if (! (input = GetInput(argc, argv))) + { + return 1; + } + + char Desc[] = "string optimization, string operation, int mode, matrix A, matrix B, int row, int column, int rows, int columns, int repetitions, int size, string speedtest"; + char Operation[128], optimization[128], speedtest[128]; + matrix A, B; + int *Filled; + int Mode, Row, Column, Rows, Columns, Reps, Size, Optimized, SpeedTest; + MemoryManager mem; + + mem = CreateMemoryManager(5, 2, 0, 0); + SetDefaults(optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size, speedtest); + while (ParseStructure(input, Desc, &Filled, &mem, optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size)) + { + Optimized = ! strcmp(optimization, "yes"); + if (Optimized) Mode = -1; + SpeedTest = ! strcmp(speedtest, "yes"); + if (! Filled[FF_OPERATION]) + { + printf("Warning: No operation code specified. Skipping problem.\n"); + } + else if (! strcmp(Operation, "InsertRows")) + { + if (SpeedTest) + { + SInsertR(Size, Reps, Row, Rows, Optimized); + } + else + { + TInsertR(&A, &B, Row, Mode, Optimized); + } + } + else if (! strcmp(Operation, "InsertColumns")) + { + if (SpeedTest) + { + SInsertC(Size, Reps, Column, Columns, Optimized); + } + else + { + TInsertC(&A, &B, Column, Mode, Optimized); + } + } + else if (! strcmp(Operation, "InsertNullRows")) + { + if (SpeedTest) + { + SInsertNullR(Size, Reps, Row, Rows, Optimized); + } + else + { + TInsertNullR(&A, Row, Rows, Mode, Optimized); + } + } + else if (! strcmp(Operation, "InsertNullColumns")) + { + if (SpeedTest) + { + SInsertNullC(Size, Reps, Column, Columns, Optimized); + } + else + { + TInsertNullC(&A, Column, Columns, Mode, Optimized); + } + } + else if (! strcmp(Operation, "RemoveRows")) + { + if (SpeedTest) + { + SRemoveR(Size, Reps, Row, Rows, Optimized); + } + else + { + TRemoveR(&A, Row, Rows, Mode, Optimized); + } + } + else if (! strcmp(Operation, "RemoveColumns")) + { + if (SpeedTest) + { + SRemoveC(Size, Reps, Column, Columns, Optimized); + } + else + { + TRemoveC(&A, Column, Columns, Mode, Optimized); + } + } + else + { + printf("Warning: Unrecognized operation '%s'.\n", Operation); + } + printf("-------------------------------------------------------------------------------\n"); + FreeMemory(&mem); + mem = CreateMemoryManager(10, 2, 0, 0); + SetDefaults(optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size, speedtest); + } + FreeMemory(&mem); + return 0; +} + +void SInsertR(int Size, int Reps, int Row, int Rows, int Optimized) +{ + printf("Speed-testing row insertion (%s).\n", Optimized ? "optimized" : "unoptimized"); + printf("Inserting %d rows into a square matrix of size %d, %d times...\n", Rows, Size, Reps); + + matrix *outer = AllocateMatrices(Size, Size, Reps, ! Optimized); + matrix *inner = AllocateMatrices(Rows, Size, Reps, ! Optimized); + ShowMatrix(outer, "Sample Matrix Before"); + clock_t t0 = clock(); + int i; + for (i = 0; i < Reps; i++) + { + InsertRows(outer + i, inner + i, Row, -1); + } + double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); + ShowMatrix(outer, "Sample Matrix After"); + printf("Time: %.2f ms", time / 1000.0); + DeallocateMatrices(Reps, outer); +} + +void SInsertC(int Size, int Reps, int Col, int Cols, int Optimized) +{ + printf("Speed-testing column insertion (%s).\n", Optimized ? "optimized" : "unoptimized"); + printf("Inserting %d columns into a square matrix of size %d, %d times...\n", Cols, Size, Reps); + + matrix *outer = AllocateMatrices(Size, Size, Reps, Optimized); + matrix *inner = AllocateMatrices(Size, Cols, Reps, Optimized); + ShowMatrix(outer, "Sample Matrix Before"); + clock_t t0 = clock(); + int i; + for (i = 0; i < Reps; i++) + { + InsertColumns(outer + i, inner + i, Col, -1); + } + double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); + ShowMatrix(outer, "Sample Matrix After"); + printf("Time: %.2f ms", time / 1000.0); + DeallocateMatrices(Reps, outer); +} + +void TInsertR(matrix *A, matrix *B, int Row, int Mode, int Optimized) +{ + printf("Testing row insertion: B -> A at row %d...\n", Row); + printf("Mode: %d. Optimization: %s.\n", Mode, Optimized ? "Yes" : "No"); + matrix A1, B1; + if (Optimized) + { + AllocateMatrixType(2, &A1, NumberOfRows(*A), NumberOfColumns(*A)); + CopyMatrix(A, &A1); + AllocateMatrixType(2, &B1, NumberOfRows(*B), NumberOfColumns(*B)); + CopyMatrix(B, &B1); + } + else + { + AllocateMatrixType(2, &A1, NumberOfColumns(*A), NumberOfRows(*A)); + TransposeMatrix(&A1); + CopyMatrix(A, &A1); + AllocateMatrixType(2, &B1, NumberOfColumns(*B), NumberOfRows(*B)); + TransposeMatrix(&B1); + CopyMatrix(B, &B1); + } + + ShowMatrix(&A1, "A"); + ShowMatrix(&B1, "B"); + matrix result; + result = InsertRows(&A1, &B1, Row, Mode); + ShowMatrix(Mode < 0 ? &A1 : &result, "result"); + + DeallocateMatrix(&A1); + if (B1.type) DeallocateMatrix(&B1); + if (Mode >= 0) DeallocateMatrix(&result); +} + +void TInsertC(matrix *A, matrix *B, int Col, int Mode, int Optimized) +{ + printf("Testing column insertion: B -> A at column %d...\n", Col); + printf("Mode: %d. Optimization: %s.\n", Mode, Optimized ? "Yes" : "No"); + matrix A1, B1; + if (! Optimized) + { + AllocateMatrixType(2, &A1, NumberOfRows(*A), NumberOfColumns(*A)); + CopyMatrix(A, &A1); + AllocateMatrixType(2, &B1, NumberOfRows(*B), NumberOfColumns(*B)); + CopyMatrix(B, &B1); + } + else + { + AllocateMatrixType(2, &A1, NumberOfColumns(*A), NumberOfRows(*A)); + TransposeMatrix(&A1); + CopyMatrix(A, &A1); + AllocateMatrixType(2, &B1, NumberOfColumns(*B), NumberOfRows(*B)); + TransposeMatrix(&B1); + CopyMatrix(B, &B1); + } + + ShowMatrix(&A1, "A"); + ShowMatrix(&B1, "B"); + matrix result; + result = InsertColumns(&A1, &B1, Col, Mode); + ShowMatrix(Mode < 0 ? &A1 : &result, "result"); + + DeallocateMatrix(&A1); + if (B1.type) DeallocateMatrix(&B1); + if (Mode >= 0) DeallocateMatrix(&result); +} + +void SRemoveR(int Size, int Reps, int Row, int Rows, int Optimized) +{ + printf("Speed-testing row removal (%s).\n", Optimized ? "optimized" : "unoptimized"); + printf("Removing %d rows from a square matrix of size %d, %d times...\n", Rows, Size, Reps); + + matrix *m = AllocateMatrices(Size, Size, Reps, ! Optimized); + + ShowMatrix(m, "Sample Matrix Before"); + clock_t t0 = clock(); + int i; + for (i = 0; i < Reps; i++) + { + RemoveRows(m + i, Row, Rows, -1); + } + double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); + ShowMatrix(m, "Sample Matrix After"); + printf("Time: %.2f ms", time / 1000.0); + DeallocateMatrices(Reps, m); +} + +void SRemoveC(int Size, int Reps, int Col, int Cols, int Optimized) +{ + printf("Speed-testing column removal (%s).\n", Optimized ? "optimized" : "unoptimized"); + printf("Removing %d columns from a square matrix of size %d, %d times...\n", Cols, Size, Reps); + + matrix *m = AllocateMatrices(Size, Size, Reps, Optimized); + + ShowMatrix(m, "Sample Matrix Before"); + clock_t t0 = clock(); + int i; + for (i = 0; i < Reps; i++) + { + RemoveColumns(m + i, Col, Cols, -1); + } + double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); + ShowMatrix(m, "Sample Matrix After"); + printf("Time: %.2f ms", time / 1000.0); + DeallocateMatrices(Reps, m); +} + +void TRemoveR(matrix *A, int Row, int Rows, int Mode, int Optimized) +{ + printf("Testing row removal: %d rows from A at row %d.\n", Rows, Row); + printf("Mode: %d. Optimization: %s.\n", Mode, Optimized ? "Yes" : "No"); + matrix A1; + if (Optimized) + { + AllocateMatrixType(2, &A1, NumberOfRows(*A), NumberOfColumns(*A)); + CopyMatrix(A, &A1); + } + else + { + AllocateMatrixType(2, &A1, NumberOfColumns(*A), NumberOfRows(*A)); + TransposeMatrix(&A1); + CopyMatrix(A, &A1); + } + + ShowMatrix(&A1, "A Before"); + matrix result; + result = RemoveRows(&A1, Row, Rows, Mode); + ShowMatrix(Mode < 0 ? &A1 : &result, "A After"); + + DeallocateMatrix(&A1); + if (Mode >= 0) DeallocateMatrix(&result); +} + +void TRemoveC(matrix *A, int Col, int Cols, int Mode, int Optimized) +{ + printf("Testing column removal: %d columns from A at column %d.\n", Cols, Col); + printf("Mode: %d. Optimization: %s.\n", Mode, Optimized ? "Yes" : "No");... [truncated message content] |
From: <Ste...@us...> - 2009-07-13 18:01:17
|
Revision: 195 http://pntool.svn.sourceforge.net/pntool/?rev=195&view=rev Author: StephenCamp Date: 2009-07-13 18:01:14 +0000 (Mon, 13 Jul 2009) Log Message: ----------- Changed functions available in matrixmath.c/h: * Replaced Concatenation functions with InsertRows & InsertColumns, which function the same way but allow for the new rows or columns to be placed anywhere, not just at the end of the matrix. * Changed some names. To create a new matrix that is a copy of an old matrix with new blank rows or columns for later filling, use InsertNewRows or InsertNewColumns. These optimize when possible (type 2 matrices of appropriate transpose state) * Added MergeRows and MergeColumns. These actually combine the allocated memory for two matrices (so the "inner" matrix should not be deallocated later - this will cause a memory error when the "outer" matrix is deallocated or vice versa). Again, these optimize when possible (type 2 matrices of appropriate transpose state) Wrote new test routines and scripts for the matrixmath functions. Updated the readme. Modified test library StructuredIO (now trims leading/trailing whitespace when reading a string) Modified Paths: -------------- spnbox/README.txt spnbox/matrixmath.c spnbox/matrixmath.h spnbox/supervis.c spnbox/tests/Makefile spnbox/tests/StructuredIO.c Added Paths: ----------- spnbox/tests/test-matrixmath.c spnbox/tests/test-matrixmath.txt Modified: spnbox/README.txt =================================================================== --- spnbox/README.txt 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/README.txt 2009-07-13 18:01:14 UTC (rev 195) @@ -12,6 +12,7 @@ make <functionname> This will generate an executable called <functionname>.exe. make all will generate test executables for all spnbox functions. +To test the various functions in the matrixmath.c file, use make matrixmath. For all with such test programs except that ipslv, the test program is implemented as a program that will read from an input stream containing text in a human-readable format, interpret the text as parameters to the function, make a function call, and display the results. For format specifications, see the comments in StructuredIO.c/h. Modified: spnbox/matrixmath.c =================================================================== --- spnbox/matrixmath.c 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/matrixmath.c 2009-07-13 18:01:14 UTC (rev 195) @@ -244,34 +244,32 @@ } } -matrix ConcatenateMatrixRows(const matrix* left, const matrix* right, matrix* dst) +matrix InsertRows(matrix* outer, matrix* inner, int start, matrix* dst) { - /*rows will store the number of rows to fill, leftcols the number of columns - in left and rightcols the number of columns in right. destination is a pointer - to the final destination matrix and destinationmatrix is a blank matrix that - will be allocated if dst is not allocated.*/ - int rows, leftcols, rightcols; matrix* destination; matrix destinationMatrix; /*Zero destinationMatrix so that it can be used as an error return value.*/ AllocateMatrix(&destinationMatrix, 0, 0); /*Check parameters. None of the pointers can be null except dst.*/ - if(! (left && right)) + if(! (outer && inner)) { - merror(0, "ConcatenateMatrixRows: One of the operands is a null pointer"); + merror(0, "InsertRows/Columns: One of the operands is a null pointer"); return destinationMatrix; + } + /*inner and outer must have the same number of columns.*/ + if (NumberOfColumns(*inner) != NumberOfColumns(*outer)) + { + merror(0, "InsertRows/Columns: The operands do not have the same number of columns/rows"); + return destinationMatrix; } - /*Get the number of rows and columns of the destination.*/ - rows = NumberOfRows(*left); - leftcols = NumberOfColumns(*left); - rightcols = NumberOfColumns(*right); - - /*left and right must have the same number of columns.*/ - if (rows != NumberOfRows(*right)) + /*If start is negative, default to adding to the end.*/ + if (start < 0) start = NumberOfRows(*outer); + /*start cannot point to a row farther out than the first possible new row*/ + if (start > NumberOfRows(*outer)) { - merror(0, "ConcatenateMatrixRows: The operands do not have the same number of rows"); + merror(0, "InsertRows/Columns: The index of the first inserted row/column is out of range"); return destinationMatrix; } @@ -281,14 +279,14 @@ { /*If the dst pointer is null, allocate a new matrix of the default type and use this as the destination matrix.*/ - AllocateMatrix(&destinationMatrix, rows, leftcols + rightcols); + AllocateMatrix(&destinationMatrix, NumberOfRows(*inner) + NumberOfRows(*outer), NumberOfColumns(*inner)); destination = &destinationMatrix; } else if((int) dst < 4) { /*If the dst pointer is between 1 and 3, treat it like an integer describing the type of the desired destination matrix.*/ - AllocateMatrixType((int) dst, &destinationMatrix, rows, leftcols + rightcols); + AllocateMatrixType((int) dst, &destinationMatrix, NumberOfRows(*inner) + NumberOfRows(*outer), NumberOfColumns(*inner)); destination = &destinationMatrix; } else @@ -296,93 +294,47 @@ /*Assume dst is a valid address. Check to make sure it has the right dimensions.*/ destination = dst; - if (! (rows == NumberOfRows(*dst) && leftcols + rightcols == NumberOfColumns(*dst))) + if (! (NumberOfRows(*inner) + NumberOfRows(*outer) == NumberOfRows(*dst) && NumberOfColumns(*inner) == NumberOfColumns(*dst))) { - merror(0, "ConcatenateMatrixRows: The destination matrix does not have the proper dimensions."); + merror(0, "InsertRows/Columns: The destination matrix does not have the proper dimensions."); return destinationMatrix; } } - /*Copy the left matrix into columns 0-NumberOfColumns(*left) - 1.*/ - CopyBlock(rows, leftcols, left, 0, 0, destination, 0, 0); - - /*Copy the right matrix into columns NumberOfColumns(*left) -> (total number - of columns)*/ - CopyBlock(rows, rightcols, right, 0, 0, destination, 0, leftcols); - - /*Return the final result.*/ - return (*destination); -} - -matrix ConcatenateMatrixCols(const matrix* top, const matrix* bottom, matrix* dst) -{ - /*cols will store the number of columns to fill, toprows the number of rows in - top and bottomrows the number of rows in bottom. destination is a pointer to - the final destination matrix and destinationmatrix is a blank matrix that will - be allocated if dst is not allocated.*/ - int cols, toprows, bottomrows; - matrix* destination; - matrix destinationMatrix; - /*Zero destinationMatrix so that it can be used as an error return value.*/ - AllocateMatrix(&destinationMatrix, 0, 0); - - /*Check parameters. None of the pointers can be null except dst.*/ - if(! (top && bottom)) + /*Copy the beforehand part of the outer matrix.*/ + if (start) { - merror(0, "ConcatenateMatrixCols: One of the operands is a null pointer"); - return destinationMatrix; + CopyBlock(start, NumberOfColumns(*outer), outer, 0, 0, destination, 0, 0); } - /*Get the number of columns and columns of the destination.*/ - cols = NumberOfColumns(*top); - bottomrows = NumberOfRows(*bottom); - toprows = NumberOfRows(*top); + /*Copy the inner matrix.*/ + CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, destination, start, 0); - /*left and right must have the same number of columns.*/ - if (cols != NumberOfColumns(*bottom)) + /*Copy the final part of the outer matrix.*/ + if (NumberOfRows(*outer) - start) { - merror(0, "ConcatenateMatrixCols: The operands do not have the same number of columns"); - return destinationMatrix; + CopyBlock(NumberOfRows(*outer) - start, NumberOfColumns(*outer), outer, start, 0, destination, start + NumberOfRows(*inner), 0); } - /*Check to see if dst has been allocated or is a number indicated the matrix - type the user wants allocated for the result.*/ - if (! dst) - { - /*If the dst pointer is null, allocate a new matrix of the default type and - use this as the destination matrix.*/ - AllocateMatrix(&destinationMatrix, toprows + bottomrows, cols); - destination = &destinationMatrix; - } - else if((int) dst < 4) - { - /*If the dst pointer is between 1 and 3, treat it like an integer describing - the type of the desired destination matrix.*/ - AllocateMatrixType((int) dst, &destinationMatrix, toprows + bottomrows, cols); - destination = &destinationMatrix; - } - else - { - /*Assume dst is a valid address. Check to make sure it has the right - dimensions.*/ - destination = dst; - if (! (cols == NumberOfColumns(*dst) && toprows + bottomrows == NumberOfRows(*dst))) - { - merror(0, "ConcatenateMatrixCols: The destination matrix does not have the proper dimensions."); - return destinationMatrix; - } - } - - /*Copy the left matrix into columns 0-NumberOfColumns(*left) - 1.*/ - CopyBlock(toprows, cols, top, 0, 0, destination, 0, 0); - - /*Copy the right matrix into columns NumberOfColumns(*left) -> (total number - of columns)*/ - CopyBlock(bottomrows, cols, bottom, 0, 0, destination, toprows, 0); - /*Return the final result.*/ return (*destination); } + +matrix InsertColumns(matrix* outer, matrix* inner, int start, matrix* dst) +{ + /*This is the column analogue of InsertRows. Transpose the operands and call + InsertRows.*/ + matrix result; + TransposeMatrix(outer); + TransposeMatrix(inner); + if ((int) dst > 3) TransposeMatrix(dst); + result = InsertRows(outer, inner, start, dst); + TransposeMatrix(outer); + TransposeMatrix(inner); + TransposeMatrix(&result); + if ((int) dst > 3) TransposeMatrix(dst); + return result; +} /*This function multiplies a particular row of the left matrix by a particular column of the right matrix. If the row or column index is a negative constaint, @@ -459,7 +411,7 @@ return 1; } -/*This function is called by AddRows and AddColumns when they detect that the +/*This function is called by InsertNewRows and InsertNewColumns when they detect that the matrix is properly formatted for optimized row/column add. It assumes that basic parameter checking has been done by AddRow and AddCol. It is a private function internal to this file.*/ @@ -493,7 +445,7 @@ m->ar = NewAr; } -/*This function is called by AddRows and AddColumns when they detect that a +/*This function is called by InsertNewRows and InsertNewColumns when they detect that a matrix is not properly formatted for fast row add. It is a private function internal to this file.*/ static void AddRowsSlow(matrix* m, int start, int rowsToAdd) @@ -588,13 +540,13 @@ *m = NewM; } -int AddRows(matrix* m, int start, int rowsToAdd) +int InsertNewRows(matrix* m, int start, int rowsToAdd) { int i; matrix NewM; if (! m) { - merror(0, "ADDROWS: Null matrix pointer"); + merror(0, "InsertNewRows/COLUMNS: Null matrix pointer"); return 0; } /*Make sure the starting point is valid. Start will be the index of the first @@ -603,13 +555,13 @@ if (start < 0) start = NumberOfRows(*m); if (start > NumberOfRows(*m)) { - merror(0, "ADDROWS: First new row index is out of range"); + merror(0, "InsertNewRows/COLUMNS: First new index is out of range"); return 0; } /*Make sure the rowsToAdd is valid. Cannot be less than 1.*/ if (rowsToAdd < 1) { - merror(0, "ADDROWS: Rows to add is negative or zero"); + merror(0, "InsertNewRows/COLUMNS: Rows/Columns to add is negative or zero"); return 0; } @@ -626,44 +578,15 @@ } } -int AddColumns(matrix* m, int start, int colsToAdd) +int InsertNewColumns(matrix* m, int start, int colsToAdd) { - if (! m) - { - merror(0, "ADDCOLUMNS: Null matrix pointer"); - return 0; - } - /*Make sure the starting point is valid. Start will be the index of the first - of the new columns added. If index < 0, default to adding at the end of the - matrix.*/ - if (start < 0) start = NumberOfColumns(*m); - if (start > NumberOfColumns(*m)) - { - merror(0, "ADDCOLUMNS: First new row index is out of range"); - return 0; - } - /*Make sure the colsToAdd is valid. Cannot be less than 1.*/ - if (colsToAdd < 1) - { - merror(0, "ADDCOLUMNS: cols to add is negative or zero"); - return 0; - } - - if (m->type == 2 && m->trans) - { - /*If matrix is a transposed type 2, the column add can be heavily - optimized.*/ - AddRowsFast(m, start, colsToAdd); - } - else - { - /*AddRowsSlow just adds rows. Transpose the matrix to do the add, then - untranspose when we're done.*/ - TransposeMatrix(m); - AddRowsSlow(m, start, colsToAdd); - TransposeMatrix(m); - } - return 1; + int result; + /*This is the column analogue of InsertNewRows. Transpose the matrix and call + InsertNewRows.*/ + TransposeMatrix(m); + result = InsertNewRows(m, start, colsToAdd); + TransposeMatrix(m); + return result; } int RemoveRows(matrix* m, int start, int rowsToRemove) @@ -671,20 +594,20 @@ /*Matrix pointer cannot be null.*/ if (! m) { - merror(0, "REMOVEROWS: Null matrix pointer"); + merror(0, "REMOVEROWS/COLUMNS: Null matrix pointer"); return 0; } /*Start has to be the index of the first row to remove.*/ if (start < 0 || start >= NumberOfRows(*m)) { - merror(0, "REMOVEROWS: Index of first row to remove is out of range"); + merror(0, "REMOVEROWS/COLUMNS: Index of first row/column to remove is out of range"); return 0; } /*The row count cannot be less than 1, nor can it be so great that it requires the removal of rows that do not exist.*/ if (rowsToRemove < 1 || start + rowsToRemove > NumberOfRows(*m)) { - merror(0, "REMOVEROWS: Number of rows to remove is out of range"); + merror(0, "REMOVEROWS/COLUMNS: Number of rows/columns to remove is out of range"); return 0; } /*See if we can optimize the removal.*/ @@ -701,38 +624,95 @@ int RemoveColumns(matrix* m, int start, int colsToRemove) { - /*Matrix pointer cannot be null.*/ - if (! m) + int result; + /*This is the column analogue of RemoveRows. Transpose the matrix and call + RemoveRows.*/ + TransposeMatrix(m); + result = RemoveRows(m, start, colsToRemove); + TransposeMatrix(m); + return result; +} + +static void MergeRowsFast(matrix *outer, matrix *inner, int start) +{ + int i; + mtype **newAr; + + newAr = tcalloc(outer->nr + inner->nr, sizeof(mtype*)); + outer->nr += inner->nr; + for (i = 0; i < outer->nr; i++) { - merror(0, "REMOVECOLUMNS: Null matrix pointer"); + if (i < start) + { + newAr[i] = outer->ar[i]; + } + else if (i < start + inner->nr) + { + newAr[i] = inner->ar[i - start]; + } + else + { + newAr[i] = outer->ar[i - inner->nr]; + } + } + free(outer->ar); + free(inner->ar); + outer->ar = newAr; + memset(inner, 0, sizeof(matrix)); +} + +int MergeRows(matrix *outer, matrix *inner, int start) +{ + /*Neither of the matrices can be null pointers.*/ + if (! (inner && outer)) + { + merror(0, "MERGEROWS/COLUMNS: Null matrix pointer"); return 0; } - /*Start has to be the index of the first column to remove.*/ - if (start < 0 || start >= NumberOfColumns(*m)) + /*If start is negative, default to adding rows at the end.*/ + if (start < 0) start = NumberOfRows(*outer); + /*We cannot add rows any farther out than the end.*/ + if (start > NumberOfRows(*outer)) { - merror(0, "REMOVECOLUMNS: Index of first column to remove is out of range"); + merror(0, "MERGEROWS/COLUMNS: Start index is out of range"); return 0; } - /*The column count cannot be less than 1, nor can it be so great that it - requires the removal of columns that do not exist.*/ - if (colsToRemove < 1 || start + colsToRemove > NumberOfColumns(*m)) + /*The matrices must have the same number of columns.*/ + if (NumberOfColumns(*outer) != NumberOfColumns(*inner)) { - merror(0, "REMOVECOLUMNS: Number of columns to remove is out of range"); + merror(0, "MERGEROWS/COLUMNS: The outer and inner matrices do not have the same number of columns"); return 0; } - /*See if we can optimize the removal.*/ - if (m->type == 2 && m->trans) + /*Attempt to optimize.*/ + if (outer->type == 2 && inner->type == 2 && ! (outer->trans || inner->trans)) { - RemoveRowsFast(m, start, colsToRemove); + MergeRowsFast(outer, inner, start); } else { - /*If not, transpose the matrix so we can use the row removal function. - Untranspose when done.*/ - TransposeMatrix(m); - RemoveRowsSlow(m, start, colsToRemove); - TransposeMatrix(m); + /*Otherwise, do a slow add and copy.*/ + InsertNewRows(outer, start, NumberOfRows(*inner)); + CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, outer, start, 0); + /*For consistencies' sake (with Fast Row Merge), deallocate the inner matrix + and zero it.*/ + DeallocateMatrix(inner); + memset(inner, 0, sizeof(matrix)); } return 1; } +int MergeColumns(matrix *outer, matrix *inner, int start) +{ + /*This is the column analogue of MergeRows. Simply transpose the operands and + call MergeRows.*/ + int result; + TransposeMatrix(outer); + TransposeMatrix(inner); + result = MergeRows(outer, inner, start); + TransposeMatrix(outer); + TransposeMatrix(inner); + return result; +} + + + Modified: spnbox/matrixmath.h =================================================================== --- spnbox/matrixmath.h 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/matrixmath.h 2009-07-13 18:01:14 UTC (rev 195) @@ -42,20 +42,23 @@ /*ShowMatrix is a debugging function that dumps the contents of a matrix to the screen in a human-readable format.*/ -matrix ConcatenateMatrixRows(const matrix* left, const matrix* right, matrix* dst); -/*ConcatenateMatrixRows returns a matrix each row of which consists of the -corresponding row of left followed to the right by the corresponding row of -right. If dst is a valid pointer the matrix to which it points is used as the -destination. If dst is null, the function allocates a new matrix of the type -determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, +matrix InsertRows(matrix* outer, matrix* inner, int start, matrix* dst); +/*InsertRows returns a matrix that is a copy of outer with the rows of inner +inserted in such a way that the first of the inserted rows has index start. If +start is negative, the inserted rows are added at the end of the matrix. +If dst is a valid pointer the matrix to which it points is used as the +destination. If dst is null, the function allocates a new matrix of the type +determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, the function allocates a new matrix of that type number.*/ -matrix ConcatenateMatrixCols(const matrix* top, const matrix* bottom, matrix* dst); -/*ConcatenateMatrixCols returns a matrix each column of which consists of the -corresponding column of top followed below by the corresponding column of -bottom. If dst is a valid pointer the matrix to which it points is used as the -destination. If dst is null, the function allocates a new matrix of the type -determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, +matrix InsertColumns(matrix* outer, matrix* inner, int start, matrix* dst); +/*InsertColumns returns a matrix that is a copy of outer with the columns of +inner inserted in such a way that the first of the inserted columns has index +start. If start is negative, the inserted columns are added at the end of the +matrix. +If dst is a valid pointer the matrix to which it points is used as the +destination. If dst is null, the function allocates a new matrix of the type +determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, the function allocates a new matrix of that type number.*/ int MultiplyVector(matrix* left, matrix* right, int Row, int Col, int Length); @@ -69,25 +72,25 @@ /*MatrixEqualMatrix tests the equality of matrices A and B. It returns nonzero if the matrices are equal and zero if they are different.*/ -int AddRows(matrix* m, int start, int rowsToAdd); -/*AddRows adds one or more contiguous rows to the given matrix. +int InsertNewRows(matrix* m, int start, int rowsToAdd); +/*InsertNewRows adds one or more contiguous rows to the given matrix. start The index of the first of the new rows. If it is set to a negative - number, AddRows adds the block of rows to the bottom of the matrix. + number, InsertNewRows adds the block of rows to the bottom of the matrix. If it is too high the function will show an error message and terminate execution. rowsToAdd The number of rows to add to the matrix. Rows will be added in a contiguous block. Return value is nonzero on success and zero on failure. -Note that if the matrix is a type-2 un-transposed, AddRows is able to invoke +Note that if the matrix is a type-2 un-transposed, InsertNewRows is able to invoke a special highly-optimized algorithm that reduces the computational complexity of the operation by at least a factor corresponding to the number of columns in the matrix.*/ -int AddColumns(matrix* m, int start, int colsToAdd); -/*AddColumns adds one or more contiguous columns to the given matrix. See -AddRows; the parameters of AddColumns are the column analogues of AddRows' +int InsertNewColumns(matrix* m, int start, int colsToAdd); +/*InsertNewColumns adds one or more contiguous columns to the given matrix. See +InsertNewRows; the parameters of InsertNewColumns are the column analogues of InsertNewRows' parameters. The return value is nonzero on success and zero on failure. -AddColumns is able to employ the same type of optimization as AddRows (decreasing +InsertNewColumns is able to employ the same type of optimization as InsertNewRows (decreasing computational complexity by a factor at least equal to the number of rows in the matrix) if and only if the matrix is a type-2 transposed.*/ @@ -100,7 +103,7 @@ the function fails with an error message and terminates execution. The return value is nonzero on success and zero on failure. If RemoveRows is passed a type-2 untransposed matrix, it employs optimization -that reduces the computational complexity of the operation by at least a +that reduces the computational complexity of the operation by at approximately a factor corresponding to the number of columns in the matrix.*/ int RemoveColumns(matrix* m, int start, int colsToRemove); @@ -108,9 +111,31 @@ See RemoveRows; the parameters of RemoveColumns are the column analogues of RemoveRows. The return value is nonzero on success and zero on failure. RemoveColumns is able to employ the same type of optimization as RemoveRows -(reducing computational copmlexity by a factor at least equal to the number of +(reducing computational complexity by a factor at least equal to the number of rows in the matrix) if and only if the matrix is a type-2 transposed.*/ +int MergeRows(matrix *outer, matrix *inner, int start); +/*MergeRows inserts the rows of the inner matrix into the outer matrix +in such a way that the first of the inserted rows has the specified start index. +Note that the function actually modifies both of the operands; it modifies the +contents of the matrix pointed to by outer by inserting the new rows, and after +inserted deallocates and zeroes the matrix pointed to by inner. The return value +is nonzero on success and zero on failure. +If both the operand matrices are type 2 untransposed, MergeRows will will employ +an optimization that will decrease computational complexity by a factor at least +equal to the number of columns in the matrices.*/ + +int MergeColumns(matrix *outer, matrix *inner, int start); +/*MergeColumns inserts the columns of the inner matrix into the outer matrix +in such a way that the first of the inserted columns has the specified start +index. Note that the function actually modifies both of the operands; it +modifies the contents of the matrix pointed to by outer by inserting the new +columns, and after inserted deallocates and zeroes the matrix pointed to by +inner. The return value is nonzero on success and zero on failure. +If both the operand matrices are type 2 transposed, MergeColumns will will +employ an optimization that will decrease computational complexity by a factor +at least equal to the number of rows in the matrices.*/ + #endif Modified: spnbox/supervis.c =================================================================== --- spnbox/supervis.c 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/supervis.c 2009-07-13 18:01:14 UTC (rev 195) @@ -89,13 +89,13 @@ AllocateMatrixType(2, &supervisorDp, k, n); d2dd(&supervisorD, &supervisorDm, &supervisorDp); - /*Concatenate the columns of the output matrices. The result should be stored - in a type-2 matrix.*/ - toReturn.Dfm = ConcatenateMatrixCols(PlantOut, &supervisorDm, (matrix*) 2); + /*Add the rows of the supervisor to the end of the net matrices. The result + should be stored in a type-2 matrix.*/ + toReturn.Dfm = InsertRows(PlantOut, &supervisorDm, -1, (matrix*) 2); /*Concatenate the columns of the input matrices. The result should be stored in a type-2 matrix.*/ - toReturn.Dfp = ConcatenateMatrixCols(PlantIn, &supervisorDp, (matrix*) 2); + toReturn.Dfp = InsertRows(PlantIn, &supervisorDp, -1, (matrix*) 2); /*Free any memory that was allocated. If we allocated new space for constraints, then a new matrix was allocated for it*/ Modified: spnbox/tests/Makefile =================================================================== --- spnbox/tests/Makefile 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/tests/Makefile 2009-07-13 18:01:14 UTC (rev 195) @@ -38,8 +38,10 @@ $(COMPILER) -o isadm.exe test-isadm.o $(COMMON) $(ISADM) issiph: test-issiph.o $(COMMON) $(ISSIPH) $(COMPILER) -o issiph.exe test-issiph.o $(COMMON) $(ISSIPH) -msplit: test-msplit.o $(MSPLIT) +msplit: test-msplit.o $(COMMON) $(MSPLIT) $(COMPILER) -o msplit.exe test-msplit.o $(COMMON) $(MSPLIT) +matrixmath: test-matrixmath.o $(COMMON) + $(COMPILER) -o matrixmath.exe test-matrixmath.o $(COMMON) pn2acpn: test-pn2acpn.o $(COMMON) $(PN2ACPN) $(COMPILER) -o pn2acpn.exe test-pn2acpn.o $(COMMON) $(PN2ACPN) supervis: test-supervis.o $(COMMON) $(SUPERVIS) @@ -124,6 +126,8 @@ $(COMPILER) -c test-isadm.c test-linenf.o: test-linenf.c $(COMMONHEADER) $(COMPILER) -c test-linenf.c +test-matrixmath.o: test-matrixmath.c $(COMMONHEADER) + $(COMPILER) -c test-matrixmath.c test-msplit.o: test-msplit.c $(COMMONHEADER) $(COMPILER) -c test-msplit.c test-nltrans.o: test-nltrans.c $(COMMONHEADER) Modified: spnbox/tests/StructuredIO.c =================================================================== --- spnbox/tests/StructuredIO.c 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/tests/StructuredIO.c 2009-07-13 18:01:14 UTC (rev 195) @@ -15,9 +15,11 @@ int An integer. double A double. string A pointer to characters. Reads a single line. - -Output descriptor string syntax is the same as for the input descriptor except that non-count array types are invalid and there is one additional type, indexarrayc, which is stored like an arrayic but displayed -as a row of X's, one in each tab-separated column corresponding to an index stored in the array. + +Output descriptor string syntax is the same as for the input descriptor except +that non-count array types are invalid and there is one additional type, +indexarrayc, which is stored like an arrayic but displayed as a row of X's, one +in each tab-separated column corresponding to an index stored in the array. */ typedef struct Parameter @@ -27,11 +29,12 @@ int Start; } Parameter; -int ParseDescription(MemoryManager* memory, char* DataDescription, Parameter** Param, int* Items); -int FindParameter(char* Name, Parameter* Param, int ParamCount); -matrix ReadMatrix(FILE* file); -double* ReadDblArray(FILE* file, int* length); -int* ReadIntArray(FILE* file, int* length); +static int ParseDescription(MemoryManager* memory, char* DataDescription, Parameter** Param, int* Items); +static int FindParameter(char* Name, Parameter* Param, int ParamCount); +static matrix ReadMatrix(FILE* file); +static double* ReadDblArray(FILE* file, int* length); +static int* ReadIntArray(FILE* file, int* length); +static void TrimWhitespace(char* string); int ParseStructure(FILE *file, char* DataDescription, int** FilledMask, MemoryManager* Memory, ...) { @@ -188,6 +191,8 @@ else if (! strcmp(Param[PID].Type, "string")) { fgets(((char*) Data[Param[PID].Start]), 128, file); + /*Trim leading and trailing whitespace.*/ + TrimWhitespace((char*) Data[Param[PID].Start]); } else { @@ -522,7 +527,7 @@ { /*If it has, empty the list and fail.*/ free(*Param); - merror(0, "READER: Data description containts duplicate item names"); + merror(0, "PARSE/DISPLAYSTRUCTURE: Data description containts duplicate item names"); return 0; } /*Add a new element to the array of parameter description structures @@ -544,7 +549,7 @@ { /*If we get here the parameter type was not recognized. Fail.*/ free(*Param); - merror(0, "READER: Bad data description type"); + merror(0, "PARSE/DISPLAYSTRUCTURE: Bad data description type"); return 0; } } @@ -555,7 +560,7 @@ Fail.*/ free(*Param); printf("Warning: Bad Data Description Group '%s %s'.\n", Type, Name); - merror(0, "READER: Bad data description group"); + merror(0, "PARSE/DISPLAYSTRUCTURE: Bad data description group"); return 0; } } while (Token = strtok(0, ",")); @@ -605,3 +610,29 @@ } return 1; } + +void TrimWhitespace(char* string) +{ + int test, flag = 0; + /*Remove leading whitespace.*/ + for (test = 0; test <= strlen(string); test++) + { + if (! (flag || isspace(string[test]))) + { + flag = test; + } + if (flag) + { + string[test - flag] = string[test]; + } + } + /*Remove trailing whitespace.*/ + for (test = strlen(string) - 1; test >= 0; test--) + { + if (! isspace(string[test])) + { + break; + } + } + string[test + 1] = '\0'; +} \ No newline at end of file Added: spnbox/tests/test-matrixmath.c =================================================================== --- spnbox/tests/test-matrixmath.c (rev 0) +++ spnbox/tests/test-matrixmath.c 2009-07-13 18:01:14 UTC (rev 195) @@ -0,0 +1,726 @@ +#include <time.h> +#include "test.h" + +#define FF_OPTION 0 +#define FF_OPERATION 1 +#define FF_A 2 +#define FF_B 3 +#define FF_C 4 +#define FF_D 5 +#define FF_ROW 6 +#define FF_COL 7 +#define FF_ROWS 8 +#define FF_COLS 9 +#define FF_REPS 10 +#define FF_SIZE 11 + +static void TestAdd(matrix *A, matrix *B, char *Option, int *Filled); +static void TestSubtract(matrix *A, matrix *B, char *Option, int *Filled); +static void TestMultiply(matrix *A, matrix *B, char *Option, int *Filled); +static void TestInsertRows(matrix *A, matrix *B, int Row, char *Option, int *Filled); +static void TestInsertColumns(matrix *A, matrix *B, int Column, char *Option, int *Filled); +static void TestMultiplyVector(matrix *A, matrix *B, int* C, int *D, int Row, int Column, int Size, int *Filled); +static void TestMatrixEqualMatrix(matrix *A, matrix *B, int* Filled); +static void TestInsertNewRows(matrix *A, int Row, int Rows, int Reps, int Size, char* Option, int *Filled); +static void TestInsertNewColumns(matrix *A, int Column, int Columns, int Reps, int Size, char* Option, int *Filled); +static void TestRemoveRows(matrix *A, int row, int rows, int Reps, int Size, char* Option, int *Filled); +static void TestRemoveColumns(matrix *A, int column, int columns, int Reps, int Size, char* Option, int *Filled); +static void TestMergeRows(matrix *A, matrix *B, int row, int Reps, int Size, char* Option, int *Filled); +static void TestMergeColumns(matrix *A, matrix *B, int column, int Reps, int Size, char* Option, int *Filled); +static int ReadAllocationOption(char* Option, int* Filled); +static void SetPointers(matrix **A, matrix **B, int **C, int **D, int* Filled); +static void PrintPercent(int num, int denom); +static void AllocateMatrices(int reps, int size, matrix **m, int Transpose); +static void DeallocateMatrices(int reps, matrix *m); +static void ShowArray(int *array, int Count, char* name); +static void SetDefaults(int* Filled, int* Row, int* Col, int* Rows, int* Cols, int* Reps, int* Size); + +int main(int argc, char* argv[]) +{ + FILE* input; + + input = GetInput(argc, argv); + + char Desc[] = "string option, string operation, matrix A, matrix B, arrayi C, arrayi D, int row, int column, int rows, int columns, int repetitions, int size"; + char Operation[128], Option[128]; + matrix A, B; + int *C, *D, *Filled; + int CCount, DCount, Row, Column, Rows, Columns, Reps, Size; + MemoryManager mem; + + mem = CreateMemoryManager(5, 2, 0, 0); + + while (ParseStructure(input, Desc, &Filled, &mem, Option, Operation, &A, &B, &C, &CCount, &D, &DCount, &Row, &Column, &Rows, &Columns, &Reps, &Size)) + { + SetDefaults(Filled, &Row, &Column, &Rows, &Columns, &Reps, &Size); + if (! Filled[FF_OPERATION]) + { + printf("Warning: No operation code specified. Skipping problem.\n"); + } + else if (! strcmp(Operation, "AddMatrix")) + { + TestAdd(&A, &B, Option, Filled); + } + else if (! strcmp(Operation, "SubtractMatrix")) + { + TestSubtract(&A, &B, Option, Filled); + } + else if (! strcmp(Operation, "MultiplyMatrix")) + { + TestMultiply(&A, &B, Option, Filled); + } + else if (! strcmp(Operation, "InsertRows")) + { + TestInsertRows(&A, &B, Row, Option, Filled); + } + else if (! strcmp(Operation, "InsertColumns")) + { + TestInsertColumns(&A, &B, Column, Option, Filled); + } + else if (! strcmp(Operation, "MultiplyVector")) + { + TestMultiplyVector(&A, &B, C, D, Row, Column, Size, Filled); + } + else if (! strcmp(Operation, "MatrixEqualMatrix")) + { + TestMatrixEqualMatrix(&A, &B, Filled); + } + else if (! strcmp(Operation, "InsertNewRows")) + { + TestInsertNewRows(&A, Row, Rows, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "InsertNewColumns")) + { + TestInsertNewColumns(&A, Column, Columns, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "RemoveRows")) + { + TestRemoveRows(&A, Row, Rows, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "RemoveColumns")) + { + TestRemoveColumns(&A, Column, Columns, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "MergeRows")) + { + TestMergeRows(&A, &B, Row, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "MergeColumns")) + { + TestMergeColumns(&A, &B, Column, Reps, Size, Option, Filled); + } + else + { + printf("Warning: Unrecognized operation '%s'.\n", Operation); + } + printf("-------------------------------------------------------------------------------\n"); + FreeMemory(&mem); + mem = CreateMemoryManager(10, 2, 0, 0); + } + FreeMemory(&mem); + return 0; +} + +void TestAdd(matrix *A, matrix *B, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing addition A + B...\n"); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A), NumberOfColumns(*A)); + AddMatrix(A, B, &Destination); + } + else + { + Destination = AddMatrix(A, B, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestSubtract(matrix *A, matrix *B, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing subtraction A - B...\n"); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A), NumberOfColumns(*A)); + SubtractMatrix(A, B, &Destination); + } + else + { + Destination = SubtractMatrix(A, B, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestMultiply(matrix *A, matrix *B, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing matrix multiplication A * B...\n"); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A), NumberOfColumns(*B)); + MultiplyMatrix(A, B, &Destination); + } + else + { + Destination = MultiplyMatrix(A, B, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestInsertRows(matrix *A, matrix *B, int Row, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing row insertion B -> A at row %d.\n", Row); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A) + NumberOfRows(*B), NumberOfColumns(*A)); + InsertRows(A, B, Row, &Destination); + } + else + { + Destination = InsertRows(A, B, Row, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestInsertColumns(matrix *A, matrix *B, int Column, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing column insertion B -> A at column %d.\n", Column); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A), NumberOfColumns(*A) + NumberOfColumns(*B)); + InsertColumns(A, B, Column, &Destination); + } + else + { + Destination = InsertColumns(A, B, Column, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestMultiplyVector(matrix *A, matrix *B, int* C, int *D, int Row, int Column, int Size, int *Filled) +{ + SetPointers(&A, &B, &C, &D, Filled); + char *message; + /*Determine the multiplication mode based on what is and isn't filled in.*/ + int Mode = 0, ModeSet = 0; + if (Filled[FF_A] && Filled[FF_B]) + { + printf("Testing vector multiplication A(%d,:) * B(:,%d)...\n", Row, Column); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + printf("Result: %d\n", MultiplyVector(A, B, Row, Column, 0)); + } + else if (Filled[FF_A]) + { + if (! Filled[FF_C]) C = D; + printf("Testing vector multiplication A(%d,:) * V...\n", Row); + ShowMatrix(A, "A"); + ShowArray(C, NumberOfColumns(*A), "V"); + printf("Result: %d\n", MultiplyVector(A, (matrix*) C, Row, MULTIPLYVECTOR_ARRAY, 0)); + } + else if (Filled[FF_B]) + { + if (! Filled[FF_C]) C = D; + printf("Testing vector multiplication V * B(:,%d)...\n", Column); + ShowArray(C, NumberOfColumns(*B), "V"); + ShowMatrix(B, "B"); + printf("Result: %d\n", MultiplyVector((matrix*) C, B, MULTIPLYVECTOR_ARRAY, Column, 0)); + } + else + { + + printf("Testing vector multiplication V1 * V2...\n"); + ShowArray(C, Size, "V1"); + ShowArray(D, Size, "V2"); + printf("Result: %d\n", MultiplyVector((matrix*) C, (matrix*) D, MULTIPLYVECTOR_ARRAY, MULTIPLYVECTOR_ARRAY, Size)); + } +} + +void TestMatrixEqualMatrix(matrix *A, matrix *B, int* Filled) +{ + SetPointers(&A, &B, 0, 0, Filled); + printf("Testing equality test A = B...\n"); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + printf("Result: %d\n", MatrixEqualMatrix(A, B)); +} + +void TestInsertNewRows(matrix *A, int Row, int Rows, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized new row insertion by inserting %d rows into square matrices of size %d, %d times...\n", Rows, Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 0); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + InsertNewRows(m + i, Row, Rows); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized new row insertion by inserting %d rows into square matrices of size %d, %d times...\n", Rows, Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 1); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + InsertNewRows(m + i, Row, Rows); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else + { + if (! Filled[FF_A]) A = 0; + + printf("Testing new row insertion of %d rows starting at row %d...\n", Rows, Row); + ShowMatrix(A, "A Before"); + InsertNewRows(A, Row, Rows); + ShowMatrix(A, "A After"); + } +} + +void TestInsertNewColumns(matrix *A, int Column, int Columns, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized new column insertion by inserting %d columns into square matrices of size %d, %d times...\n", Columns, Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 1); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + InsertNewColumns(m + i, Column, Columns); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized new column insertion by inserting %d columns into square matrices of size %d, %d times...\n", Columns, Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 0); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + InsertNewColumns(m + i, Column, Columns); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else + { + if (! Filled[FF_A]) A = 0; + + printf("Testing new column insertion of %d rows starting at column %d...\n", Columns, Column); + ShowMatrix(A, "A Before"); + InsertNewColumns(A, Column, Columns); + ShowMatrix(A, "A After"); + } +} + +void TestRemoveRows(matrix *A, int row, int rows, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized row removal by removing %d rows from square matrices of size %d, %d times...\n", rows, Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 0); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + RemoveRows(m + i, row, rows); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized row removal by removing %d rows from square matrices of size %d, %d times...\n", rows, Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 1); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + RemoveRows(m + i, row, rows); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else + { + if (! Filled[FF_A]) A = 0; + + printf("Testing new row insertion of %d rows starting at row %d...\n", rows, row); + ShowMatrix(A, "A Before"); + RemoveRows(A, row, rows); + ShowMatrix(A, "A After"); + } +} + +void TestRemoveColumns(matrix *A, int column, int columns, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized column removal by removing %d columns from square matrices of size %d, %d times...\n", columns, Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 1); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + RemoveColumns(m + i, column, columns); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized column removal by removing %d columns from square matrices of size %d, %d times...\n", columns, Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 0); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + RemoveColumns(m + i, column, columns); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else + { + if (! Filled[FF_A]) A = 0; + + printf("Testing new column insertion of %d columns starting at column %d...\n", columns, column); + ShowMatrix(A, "A Before"); + RemoveColumns(A, column, columns); + ShowMatrix(A, "A After"); + } +} + +void TestMergeRows(matrix *A, matrix *B, int row, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m1, *m2; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized row merge by merging by row two square matrices of size %d, %d times...\n", Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m1, 0); + AllocateMatrices(Reps, Size, &m2, 0); + ShowMatrix(m1, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + MergeRows(m1 + i, m2 + i, row); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m1, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m1); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized row merge by merging by row two square matrices of size %d, %d times...\n", Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m1, 1); + AllocateMatrices(Reps, Size, &m2, 1); + ShowMatrix(m1, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + MergeRows(m1 + i, m2 + i, row); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m1, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m1); + } + else + { + if (! Filled[FF_A]) A = 0; + /*Build a new copy of B - we cannot do a merge with the old one because + it will be deallocated by the merge and then the final deallocation will + fail.*/ + matrix New; + AllocateMatrixType(1, &New, NumberOfRows(*B), NumberOfColumns(*B)); + CopyMatrix(B, &New); + printf("Testing row merge B -> A starting at row %d...", row); + ShowMatrix(A, "A Before"); + ShowMatrix(&New, "B"); + MergeRows(A, &New, row); + ShowMatrix(A, "A After"); + } +} + +void TestMergeColumns(matrix *A, matrix *B, int column, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m1, *m2; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized column merge by merging by column two square matrices of size %d, %d times...\n", Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m1, 1); + AllocateMatrices(Reps, Size, &m2, 1); + ShowMatrix(m1, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + MergeColumns(m1 + i, m2 + i, column); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m1, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m1); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized column merge by merging by column two square matrices of size %d, %d times...\n", Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m1, 0); + AllocateMatrices(Reps, Size, &m2, 0); + ShowMatrix(m1, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + MergeColumns(m1 + i, m2 + i, column); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m1, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m1); + } + else + { + if (! Filled[FF_A]) A = 0; + /*Build a new copy of B - we cannot do a merge with the old one because + it will be deallocated by the merge and then the final deallocation will + fail.*/ + matrix New; + AllocateMatrixType(1, &New, NumberOfRows(*B), NumberOfColumns(*B)); + CopyMatrix(B, &New); + printf("Testing column merge B -> A starting at column %d...", column); + ShowMatrix(A, "A Before"); + ShowMatrix(&New, "B"); + MergeColumns(A, &New, column); + ShowMatrix(A, "A After"); + } +} + +/*Interpret the how-to-allocate option for an operation that can either use +pre-allocated result storage, allocate its own, or allocate its own of a +specified type.*/ +int ReadAllocationOption(char* Option, int* Filled) +{ + if (! Filled[FF_OPTION]) return -1; + if (! strcmp(Option, "preallocate")) + { + return -1; + } + else if (! strcmp(Option, "allocate")) + { + return 0; + } + else if (! strcmp(Option, "type1")) + { + return 1; + } + else if (! strcmp(Option, "type2")) + { + return 2; + } + else if (! strcmp(Option, "type3")) + { + return 3; + } + else + { + printf("Warning: Unrecognized allocation option '%s'. Preallocating.\n", Option); + return -1; + } +} + +/*Make sure that pointers to matrices and arrays are null if the arrays and +matrices were not given in the problem data.*/ +void SetPointers(matrix **A, matrix **B, int **C, int **D, int* Filled) +{ + if ((! Filled[FF_A]) && A) *A = 0; + if ((! Filled[FF_B]) && B) *B = 0; + if ((! Filled[FF_C]) && C) *C = 0; + if ((! Filled[FF_D]) && D) *D = 0; +} + +/*Display a progress percentage that changes with time instead of being left +in the output buffer.*/ +void PrintPercent(int num, int denom) +{ + static int lastPercent = -1; + int percent; + percent = (num * 100) / denom; + if (percent != lastPercent) + { + lastPercent = percent; + if (percent) printf("\b\b\b\b"); + printf("%3d%%", percent); + fflush(stdout); + } +} + +/*Allocate an array of matrices to be used for a speed test.*/ +void AllocateMatrices(int reps, int size, matrix **m, int Transpose) +{ + int i; + *m = tcalloc(reps, sizeof(matrix)); + printf("Allocating test matrices..."); + PrintPercent(0, 1); + for (i = 0; i < reps; i++) + { + AllocateMatrixType(2, (*m) + i, size, size); + if (Transpose) TransposeMatrix((*m) + i); + PrintPercent(i + 1, reps); + } + printf("\n"); +} + +/*Deallocate an array of matrices that have been allocated for a speed test.*/ +void DeallocateMatrices(int reps, matrix *m) +{ + int i; + printf("Deallocating test matrices..."); + PrintPercent(0, 1); + for (i = 0; i < reps; i++) + { + DeallocateMatrix(m + i); + PrintPercent(i + 1, reps); + } + printf("\n"); + free(m); +} + +/*Used by TestMultiplyVector to show array-type vectors.*/ +void ShowArray(int *array, int Count, char* name) +{ + int i; + if (! array) + { + printf("ShowArray: Null array pointer"); + return; + } + printf("%s\t", name); + for (i = 0; i < Count; i++) + { + printf("%d\t", array[i]); + } + printf("\n"); +} + +void SetDefaults(int* Filled, int* Row, int* Col, int* Rows, int* Cols, int* Reps, int* Size) +{ + if (! Filled[FF_ROW]) *Row = -1; + if (! Filled[FF_COL]) *Col = -1; + if (! Filled[FF_ROWS]) *Rows = 0; + if (! Filled[FF_COLS]) *Cols = 0; + if (! Filled[FF_REPS]) *Reps = 1; + if (! Filled[FF_SIZE]) *Size = 0; +} \ No newline at end of file Added: spnbox/tests/test-matrixmath.txt =================================================================== --- spnbox/tests/test-matrixmath.txt (rev 0) +++ spnbox/tests/test-matrixmath.txt 2009-07-13 18:01:14 UTC (rev 195) @@ -0,0 +1,348 @@ +rem string option, string operation, matrix A, matrix B, arrayi C, arrayi D, +rem int row, int column, int rows, int columns, int repetitions, int size +rem Operation Operands Options +rem AddMatrix A, B preallocate, allocate, type1, type2, type3 +rem SubtractMatrix A, B preallocate, allocate, type1, type2, type3 +rem MultiplyMatrix A, B preallocate, allocate, type1, type2, type3 +rem InsertRows A, B, Row preallocate, allocate, type1, type2, type3 +rem InsertColumns A, B, Column preallocate, allocate, type1, type2, type3 +rem MultiplyVector (A, B) or (A, C or D) +rem or (B, C or D) +rem MatrixEqualMatrix A, B +rem InsertNewRows [A], Row, Rows +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem InsertNewColumns [A], Column, Columns +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem RemoveRows [A], Row, Rows +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem RemoveColumns [A], Column, Columns +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem MergeRows [A, B,] Row, +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem MergeColumns [A, B,] Column, +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized + +echo Problem 1. Addition Test with preallocated result space. +operation AddMatrix +A 3 3 +1 2 3 +4 5 6 +7 8 9 + +B 3 3 +9 8 7 +6 5 4 +3 2 1 + +done + +echo Problem 2. Addition test with self-allocated result space. +operation AddMatrix +option allocate +A 2 2 +1 2 +3 4 + +B 2 2 +3 4 +2 1 + +done + +echo Problem 3. Subtraction test with specific type self-allocated result space. +operation SubtractMatrix +option type1 +A 3 3 +9 9 9 +9 9 9 +9 9 9 + +B 3 3 +9 8 7 +6 5 4 +3 2 1 + +done + +echo Problem 4. Multiplication test with explicit preallocated result space. +operation MultiplyMatrix +option preallocate +A 2 3 +1 2 1 +2 1 2 + +B 3 1 +1 2 3 + +done + +echo Problem 5. Inserted rows from one matrix into another matrix. +operation InsertRows +A 2 3 +1 2 3 +7 8 9 + +B 1 3 +4 5 6 + +row 1 +done + +echo Problem 6. Inserting columns from one matrix into another matrix. +operation InsertColumns +A 3 2 +1 7 +2 8 +3 9 + +B 3 1 +4 +5 +6 + +column 1 +done + +echo Problem 7. MultiplyVector with integer arrays. +echo The answer should be 19. +operation MultiplyVector +C 3 +1 2 3 + +D 3 +3 5 2 + +size 3 +done + +echo Problem 7. MultiplyVector with one matrix and one integer array. +echo The answer should be 19. +operation MultiplyVector +A 3 3 +0 0 0 +1 2 3 +0 0 0 + +C 3 +3 5 2 + +row 1 +done + +echo Problem 8. MultiplyVector with one integer array and one matrix. +echo The answer should be 19. +operation MultiplyVector +D 3 +3 5 2 + +B 3 3 +0 1 0 +0 2 0 +0 3 0 + +column 1 +done + +echo Problem 9. MultiplyVector with two matrices. +echo The answer should be 19. +operation MultiplyVector +A 3 3 +0 0 0 +0 0 0 +3 5 2 + +B 3 3 +1 0 0 +2 0 0 +3 0 0 + +column 0 +row 2 +done + +echo Problem 10. Matrix equality test with equal matrices. +operation MatrixEqualMatrix +A 2 2 +1 2 +3 4 + +B 2 2 +1 2 +3 4 + +done + +echo Problem 11. Matrix equality test with unequal matrices. +operation MatrixEqualMatrix +A 2 2 +1 2 +3 4 + +B 2 2 +1 2 +3 1 + +done +echo Problem 12. Matrix equality test with matrices of different sizes. +operation MatrixEqualMatrix +A 2 2 +1 1 +1 1 + +B 1 1 +1 +done + +echo Problem 13. New row insertion. +operation InsertNewRows +A 2 3 +1 2 3 +2 4 6 + +row 1 +rows 2 +done + +echo Problem 14. New column insertion. +operation InsertNewColumns +A 2 2 +1 2 +1 2 + +columns 3 +done + +echo Problem 15. Row removal. +operation RemoveRows +A 4 2 +1 1 +0 0 +2 2 +3 3 + +row 1 +rows 2 +done + +echo Problem 16. Column removal. +operation RemoveColumns +A 2 4 +1 1 2 3 +1 4 5 6 + +column 0 +columns 1 +done + +echo Problem 16. Row merge. +operation MergeRows +A 2 3 +1 2 3 +7 8 9 + +B 1 3 +4 5 6 +row 1 + +done + +echo Problem 17. Column merge. +operation MergeColumns +A 3 2 +1 7 +2 8 +3 9 + +B 3 1 +4 +5 +6 + +column 1 +done + +echo Speed Test: InsertNewRows, unoptimized +operation InsertNewRows +size 10 +rows 1 +repetitions 40000 +option speedtest-unoptimized +done + +echo Speed Test: InsertNewRows, optimized +operation InsertNewRows +size 10 +rows 1 +repetitions 40000 +option speedtest-optimized +done + +echo Speed Test: RemoveRows, unoptimized +operation RemoveRows +size 10 +row 4 +rows 1 +repetitions 40000 +option speedtest-unoptimized +done + +echo Speed Test: RemoveRows, optimized +operation RemoveRows +size 10 +row 4 +rows 1 +repetitions 40000 +option speedtest-optimized +done + +echo Speed Test: RemoveColumns, unoptimized +operation RemoveColumns +size 10 +column 4 +columns 1 +repetitions 40000 +option speedtest-unoptimized +done + +echo Speed Test: RemoveColumns, optimized +operation RemoveColumns +size 10 +column 4 +columns 1 +repetitions 40000 +option speedtest-optimized +done + +echo Speed Test: MergeRows, unoptimized +operation MergeRows +size 10 +row 2 +repetitions 20000 +option speedtest-unoptimized +done + +echo Speed Test: MergeRows, optimized +operation MergeRows +size 10 +row 2 +repetitions 20000 +option speedtest-optimized +done + +echo Speed Test: MergeColumns, unoptimized +operation MergeColumns +size 10 +column 5 +repetitions 20000 +option speedtest-unoptimized +done + +echo Speed Test: MergeColumns, optimized +operation MergeColumns +size 10 +column 5 +repetitions 20000 +option speedtest-optimized + +done +quit This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <Ste...@us...> - 2009-07-10 04:46:48
|
Revision: 194 http://pntool.svn.sourceforge.net/pntool/?rev=194&view=rev Author: StephenCamp Date: 2009-07-10 04:46:45 +0000 (Fri, 10 Jul 2009) Log Message: ----------- Added row and column add and remove functions to matrixmath. These employ optimizations when possible based on the internals of the matrix structure - if the structure is ever changed these functions will have to be changed. Actually adding the readme file this time. Found two apparent bugs in matrix.c: GetMatrixEl and SetMatrixEl for type-1 matrices that have been transposed appear to have been swapping row and column count. Modified Paths: -------------- pnheaders/matrix.c spnbox/Makefile spnbox/matrixmath.c spnbox/matrixmath.h Added Paths: ----------- spnbox/README.txt Modified: pnheaders/matrix.c =================================================================== --- pnheaders/matrix.c 2009-07-08 20:55:01 UTC (rev 193) +++ pnheaders/matrix.c 2009-07-10 04:46:45 UTC (rev 194) @@ -80,7 +80,7 @@ mtype GetMatrixEl(const matrix* m, int i, int j) { switch(m->type) { case 1: - return m->trans?m->elem[j*m->nr+i]:m->elem[i*m->nc+j]; + 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: @@ -179,7 +179,7 @@ switch(m->type) { case 1: if(m->trans) - m->elem[j*m->nr+i] = x; + m->elem[j*m->nc+i] = x; else m->elem[i*m->nc+j] = x; break; Modified: spnbox/Makefile =================================================================== --- spnbox/Makefile 2009-07-08 20:55:01 UTC (rev 193) +++ spnbox/Makefile 2009-07-10 04:46:45 UTC (rev 194) @@ -3,7 +3,7 @@ COMPILER=gcc -g -all: actn.o chkcons.o ilpadm.o ipslv.o ipsolve.o isadm.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a +all: actn.o chkcons.o ilpadm.o ipslv.o ipsolve.o isadm.o issiph.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a actn.o: actn.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c actn.c @@ -16,13 +16,16 @@ ipslv.o: ipslv.c spnbox.h ../third-party/lp_solve_5.5/lp_lib.h $(COMPILER) -c ipslv.c - + ipsolve.o: ipsolve.c spnbox.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c ipsolve.c isadm.o: isadm.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c isadm.c +issiph.o: ../issiph.c ../spnbox.h ../../pnheaders/general.h ../../pnheaders/matrix.h + $(COMPILER) -c ../issiph.c + linenf.o: linenf.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c linenf.c Added: spnbox/README.txt =================================================================== --- spnbox/README.txt (rev 0) +++ spnbox/README.txt 2009-07-10 04:46:45 UTC (rev 194) @@ -0,0 +1,62 @@ +#ABOUT +SPNBOX implements the Petri net supervisory control functions originally developed by Dr. Iordache for Matlab. + +#COMPILING +To generate object files for the entire SPNBOX toolset, run "make" from the pntool/spnbox directory. + +Note that SPNBOX makes use of the LPSOLVE MILP solver API found in the pntool/third-party directory. The makefile will attempt to copy the compiled library liblpsolve55.a from the LPSOLVE directories into the pntool/spnbox directory if it is not already present. If the LPSOLVE library is not present in its own directory, the SPNBOX makefile will invoke LPSOLVE's linux-targeted makefile to build the lpsolve library. + +#TESTING +The subdirectory "tests" contains test files for the SPNBOX functions. There are source files for a test program for each function except chkcons, which is used as a subroutine of other functions and so tested implicitly. +The makefile within the directory will make any of the test programs. To generate the test program for a particular function, use a command of the form: +make <functionname> +This will generate an executable called <functionname>.exe. +make all will generate test executables for all spnbox functions. + +For all with such test programs except that ipslv, the test program is implemented as a program that will read from an input stream containing text in a human-readable format, interpret the text as parameters to the function, make a function call, and display the results. For format specifications, see the comments in StructuredIO.c/h. + +The programs may be invoked with a single command line argument, which will be taken as the name of a text file from which to read the input. If no command line argument is used the test programs will take input from the console. + +Pre-formatted test scripts with problems to test each part of a function have been provided. These are named in the form test-<functionname>.txt. + +Thus, to test ipsolve with the default test script the following command sequence might be issued: + +cd ~/pntool/spnbox/tests +make ipsolve +./ipsolve test-ipsolve.txt + +#FILES +Main directory: +- spnbox.h: This is the header file containing the definitions for all the SPNBOX + functions, as well as various constant definitions. +- matrixmath.h & matrixmath.c: These implement various matrix operations used by + other SPNBOX functions. +- deallocation.c: This implements functions to deallocate the structures returned + by SPNBOX functions. +- Makefile: This is the main makefile. When used without a target it builds + object files that implement all SPNBOX functionality. It can take as a target + the command "clean", upon reciept of which it removes all object files, all + library (*.a) files, moves to the third-party/lp_solve_5.5/ directory, and + executes the linux-targeted makefile to clean the lpsolve libraries and + intermediate files. +- Each of the other files corresponds to a single SPNBOX function. + +tests subdirectory: +- test.c & test.h: These define and implement a few subroutines used by many of + the test programs as well as implemented the pntool "is_verbose" function to + ensure maximum verbosity during testing. The header file also includes header + files common to all the test programs. +- StructuredIO.c & StructuredIO.h: These define and implement a pair of functions, + ParseStructure and DisplayStructure. ParseStructure is used used to parse human- + readable text from a stream as described in a format string and with it fill + an arbitrary number of variables. It is an analogue of sprintf with support + for more complex data structures such as arrays and matrices. + DisplayStructure is used to display such data structures in a human-readable + format as described by a similar format string. For usage and format string + information see the comments in the files. These functions are used by nearly + all the test programs to make the collection of input easier. +- Makefile: This is the test makefile. It is responsible for building various + test routines and takes targets as described above in #TESTING. +- All other files are the source files for the test executables for various + functions. + Modified: spnbox/matrixmath.c =================================================================== --- spnbox/matrixmath.c 2009-07-08 20:55:01 UTC (rev 193) +++ spnbox/matrixmath.c 2009-07-10 04:46:45 UTC (rev 194) @@ -459,3 +459,280 @@ return 1; } +/*This function is called by AddRows and AddColumns when they detect that the +matrix is properly formatted for optimized row/column add. It assumes that +basic parameter checking has been done by AddRow and AddCol. It is a private +function internal to this file.*/ +static void AddRowsFast(matrix* m, int start, int rowsToAdd) +{ + int i; + mtype** NewAr; + m->nr += rowsToAdd; + NewAr = tcalloc(m->nr, sizeof(mtype*)); + for (i = 0; i < m->nr; i++) + { + /*If we have not yet reached the insertion point, copy addresses directly.*/ + if (i < start) + { + NewAr[i] = m->ar[i]; + } + /*At the insertion point, allocate space for a new row.*/ + else if (i < start + rowsToAdd) + { + NewAr[i] = tcalloc(m->nc, sizeof(mtype)); + } + /*After the insertion point, each new array element should get the value + of the previous element in the original array.*/ + else + { + NewAr[i] = m->ar[i - rowsToAdd]; + } + } + /*Free and reassign memory.*/ + free(m->ar); + m->ar = NewAr; +} + +/*This function is called by AddRows and AddColumns when they detect that a +matrix is not properly formatted for fast row add. It is a private function +internal to this file.*/ +static void AddRowsSlow(matrix* m, int start, int rowsToAdd) +{ + int i; + matrix NewM; + + /*Preserve the transpose state of the matrix.*/ + if (m->trans) + { + AllocateMatrixType(m->type, &NewM, NumberOfColumns(*m), NumberOfRows(*m) + rowsToAdd); + TransposeMatrix(&NewM); + } + else + { + AllocateMatrixType(m->type, &NewM, NumberOfRows(*m) + rowsToAdd, NumberOfColumns(*m)); + } + + for (i = 0; i < NumberOfRows(NewM); i++) + { + if (i < start) + { + CopyBlock(1, NumberOfColumns(NewM), m, i, 0, &NewM, i, 0); + } + else if (i >= start + rowsToAdd) + { + CopyBlock(1, NumberOfColumns(NewM), m, i - rowsToAdd, 0, &NewM, i, 0); + } + } + DeallocateMatrix(m); + (*m) = NewM; +} + +/*This function is called by RemoveRow and RemoveCol when they detect that the +matrix is properly formatted for an optimized row/column removal. It assumes +that basic parameter checking has been done by AddRow and AddCol. It is a +private function internal to this file.*/ +static void RemoveRowsFast(matrix* m, int start, int rowsToAdd) +{ + int i; + mtype** NewAr; + NewAr = tcalloc(m->nr, sizeof(mtype*)); + for (i = 0; i < m->nr; i++) + { + if (i < start) + { + NewAr[i] = m->ar[i]; + } + else if (i < start + rowsToAdd) + { + free(m->ar[i]); + } + else + { + NewAr[i - rowsToAdd] = m->ar[i]; + } + } + free(m->ar); + m->ar = NewAr; + m->nr -= rowsToAdd; +} + +/*This function is called by RemoveRows and RemoveColumns when they detect that +a matrix is not properly formatted for fast row removal. It is a private +function internal to this file.*/ +static int RemoveRowsSlow(matrix *m, int start, int rowsToRemove) +{ + int i; + matrix NewM; + /*Preserve the transpose state of the matrix.*/ + if (m->trans) + { + AllocateMatrixType(m->type, &NewM, NumberOfColumns(*m), NumberOfRows(*m) - rowsToRemove); + TransposeMatrix(&NewM); + } + else + { + AllocateMatrixType(m->type, &NewM, NumberOfRows(*m) - rowsToRemove, NumberOfColumns(*m)); + } + for (i = 0; i < NumberOfRows(NewM); i++) + { + if (i < start) + { + CopyBlock(1, NumberOfColumns(NewM), m, i, 0, &NewM, i, 0); + } + else + { + CopyBlock(1, NumberOfColumns(NewM), m, i + rowsToRemove, 0, &NewM, i, 0); + } + } + DeallocateMatrix(m); + *m = NewM; +} + +int AddRows(matrix* m, int start, int rowsToAdd) +{ + int i; + matrix NewM; + if (! m) + { + merror(0, "ADDROWS: Null matrix pointer"); + return 0; + } + /*Make sure the starting point is valid. Start will be the index of the first + of the new rows added. If index < 0, default to adding at the end of the + matrix.*/ + if (start < 0) start = NumberOfRows(*m); + if (start > NumberOfRows(*m)) + { + merror(0, "ADDROWS: First new row index is out of range"); + return 0; + } + /*Make sure the rowsToAdd is valid. Cannot be less than 1.*/ + if (rowsToAdd < 1) + { + merror(0, "ADDROWS: Rows to add is negative or zero"); + return 0; + } + + if (m->type == 2 && (! m->trans)) + { + /*If matrix is an untransposed type 2, the row add can be heavily + optimized.*/ + AddRowsFast(m, start, rowsToAdd); + } + else + { + AddRowsSlow(m, start, rowsToAdd); + return 1; + } +} + +int AddColumns(matrix* m, int start, int colsToAdd) +{ + if (! m) + { + merror(0, "ADDCOLUMNS: Null matrix pointer"); + return 0; + } + /*Make sure the starting point is valid. Start will be the index of the first + of the new columns added. If index < 0, default to adding at the end of the + matrix.*/ + if (start < 0) start = NumberOfColumns(*m); + if (start > NumberOfColumns(*m)) + { + merror(0, "ADDCOLUMNS: First new row index is out of range"); + return 0; + } + /*Make sure the colsToAdd is valid. Cannot be less than 1.*/ + if (colsToAdd < 1) + { + merror(0, "ADDCOLUMNS: cols to add is negative or zero"); + return 0; + } + + if (m->type == 2 && m->trans) + { + /*If matrix is a transposed type 2, the column add can be heavily + optimized.*/ + AddRowsFast(m, start, colsToAdd); + } + else + { + /*AddRowsSlow just adds rows. Transpose the matrix to do the add, then + untranspose when we're done.*/ + TransposeMatrix(m); + AddRowsSlow(m, start, colsToAdd); + TransposeMatrix(m); + } + return 1; +} + +int RemoveRows(matrix* m, int start, int rowsToRemove) +{ + /*Matrix pointer cannot be null.*/ + if (! m) + { + merror(0, "REMOVEROWS: Null matrix pointer"); + return 0; + } + /*Start has to be the index of the first row to remove.*/ + if (start < 0 || start >= NumberOfRows(*m)) + { + merror(0, "REMOVEROWS: Index of first row to remove is out of range"); + return 0; + } + /*The row count cannot be less than 1, nor can it be so great that it + requires the removal of rows that do not exist.*/ + if (rowsToRemove < 1 || start + rowsToRemove > NumberOfRows(*m)) + { + merror(0, "REMOVEROWS: Number of rows to remove is out of range"); + return 0; + } + /*See if we can optimize the removal.*/ + if (m->type == 2 && ! m->trans) + { + RemoveRowsFast(m, start, rowsToRemove); + } + else + { + RemoveRowsSlow(m, start, rowsToRemove); + } + return 1; +} + +int RemoveColumns(matrix* m, int start, int colsToRemove) +{ + /*Matrix pointer cannot be null.*/ + if (! m) + { + merror(0, "REMOVECOLUMNS: Null matrix pointer"); + return 0; + } + /*Start has to be the index of the first column to remove.*/ + if (start < 0 || start >= NumberOfColumns(*m)) + { + merror(0, "REMOVECOLUMNS: Index of first column to remove is out of range"); + return 0; + } + /*The column count cannot be less than 1, nor can it be so great that it + requires the removal of columns that do not exist.*/ + if (colsToRemove < 1 || start + colsToRemove > NumberOfColumns(*m)) + { + merror(0, "REMOVECOLUMNS: Number of columns to remove is out of range"); + return 0; + } + /*See if we can optimize the removal.*/ + if (m->type == 2 && m->trans) + { + RemoveRowsFast(m, start, colsToRemove); + } + else + { + /*If not, transpose the matrix so we can use the row removal function. + Untranspose when done.*/ + TransposeMatrix(m); + RemoveRowsSlow(m, start, colsToRemove); + TransposeMatrix(m); + } + return 1; +} + Modified: spnbox/matrixmath.h =================================================================== --- spnbox/matrixmath.h 2009-07-08 20:55:01 UTC (rev 193) +++ spnbox/matrixmath.h 2009-07-10 04:46:45 UTC (rev 194) @@ -68,6 +68,49 @@ int MatrixEqualMatrix(matrix* A, matrix* B); /*MatrixEqualMatrix tests the equality of matrices A and B. It returns nonzero if the matrices are equal and zero if they are different.*/ + +int AddRows(matrix* m, int start, int rowsToAdd); +/*AddRows adds one or more contiguous rows to the given matrix. +start The index of the first of the new rows. If it is set to a negative + number, AddRows adds the block of rows to the bottom of the matrix. + If it is too high the function will show an error message and + terminate execution. +rowsToAdd The number of rows to add to the matrix. Rows will be added in a + contiguous block. +Return value is nonzero on success and zero on failure. +Note that if the matrix is a type-2 un-transposed, AddRows is able to invoke +a special highly-optimized algorithm that reduces the computational complexity +of the operation by at least a factor corresponding to the number of columns in +the matrix.*/ + +int AddColumns(matrix* m, int start, int colsToAdd); +/*AddColumns adds one or more contiguous columns to the given matrix. See +AddRows; the parameters of AddColumns are the column analogues of AddRows' +parameters. The return value is nonzero on success and zero on failure. +AddColumns is able to employ the same type of optimization as AddRows (decreasing +computational complexity by a factor at least equal to the number of rows in the +matrix) if and only if the matrix is a type-2 transposed.*/ + +int RemoveRows(matrix* m, int start, int rowsToRemove); +/*RemoveRows removes one or more contiguous rows from the given matrix. +start The index of the first row to remove. If it is out of range the + function will fail with an error message. +rowsToRemove The number of rows to remove. If the number is less than 1 or + large enough that it would attempt to remove nonexistant rows, + the function fails with an error message and terminates execution. +The return value is nonzero on success and zero on failure. +If RemoveRows is passed a type-2 untransposed matrix, it employs optimization +that reduces the computational complexity of the operation by at least a +factor corresponding to the number of columns in the matrix.*/ + +int RemoveColumns(matrix* m, int start, int colsToRemove); +/*RemoveColumns removes one or more contiguous columns from the given matrix. +See RemoveRows; the parameters of RemoveColumns are the column analogues of +RemoveRows. The return value is nonzero on success and zero on failure. +RemoveColumns is able to employ the same type of optimization as RemoveRows +(reducing computational copmlexity by a factor at least equal to the number of +rows in the matrix) if and only if the matrix is a type-2 transposed.*/ + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Drew C. <dr...@se...> - 2009-07-09 11:26:13
|
This appears to be related to the definition of process->include, which is of type char*. I've examined the memory in gdb and indeed it contains a char*. plantCompiler.c:143 treats the process->include it is passed as a text* type. The begin and end longs of the "struct" are invalid memory. The build process emits the folowing warning: src/plantCompiler.c: In function ‘compileProcessArray’: src/plantCompiler.c:46: warning: passing argument 3 of ‘compileSinglePlant’ from incompatible pointer type Which appears to be the issue in question. --Drew |
From: <the...@us...> - 2009-07-08 20:55:04
|
Revision: 193 http://pntool.svn.sourceforge.net/pntool/?rev=193&view=rev Author: thecodeweasel Date: 2009-07-08 20:55:01 +0000 (Wed, 08 Jul 2009) Log Message: ----------- Forgot to turn off debugging Modified Paths: -------------- translator/pncompactor.c translator/pncompactor.g translator/pncompactor.h Modified: translator/pncompactor.c =================================================================== --- translator/pncompactor.c 2009-07-08 20:52:51 UTC (rev 192) +++ translator/pncompactor.c 2009-07-08 20:55:01 UTC (rev 193) @@ -2,7 +2,7 @@ * This C source file was generated by $ANTLR version 3.1.2 * * - From the grammar source file : /Users/bion/projects/iordache/translator/pncompactor.g - * - On : 2009-07-08 15:50:56 + * - On : 2009-07-08 15:54:37 * - for the tree parser : pncompactorTreeParser * * Editing it, at least manually, is not wise. * @@ -47,7 +47,7 @@ #include <stdbool.h> #include "general.h" - #define DEBUG true + #define DEBUG false /* End of Header action. * ============================================================================= @@ -3863,7 +3863,7 @@ /* AST REWRITE - * elements : add1, add2, EQ_OP, add1, EQ_OP, EQ_OP, add2, EQ_OP, add1, EQ_OP, add1, add2, add2, EQ_OP + * elements : add1, add1, EQ_OP, add2, EQ_OP, EQ_OP, add2, EQ_OP, add2, EQ_OP, EQ_OP, add2, add1, add1 * token labels : * rule labels : add2, add1, retval * token list labels : @@ -4386,19 +4386,19 @@ /* AST REWRITE - * elements : add1, add2, add2, PLUS, add2, add1, PLUS, add2, add1 + * elements : add2, add1, add2, add2, add1, PLUS, add2, add1, PLUS * token labels : - * rule labels : add2, add1, retval + * rule labels : add1, add2, retval * token list labels : * rule list labels : */ { + pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add1; pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add2; - pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add1; pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_retval; + stream_add1=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add1", add1.tree != NULL ? add1.tree : NULL); stream_add2=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add2", add2.tree != NULL ? add2.tree : NULL); - stream_add1=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add1", add1.tree != NULL ? add1.tree : NULL); stream_retval=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token retval", retval.tree != NULL ? retval.tree : NULL); root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -4511,8 +4511,8 @@ } retval.tree = root_0; // set result root + if (stream_add1 != NULL) stream_add1->free(stream_add1); if (stream_add2 != NULL) stream_add2->free(stream_add2); - if (stream_add1 != NULL) stream_add1->free(stream_add1); if (stream_retval != NULL) stream_retval->free(stream_retval); @@ -4610,19 +4610,19 @@ /* AST REWRITE - * elements : add1, add1, add2, MINUS, add2, add2, add1, add2 + * elements : add2, add1, add1, add1, add2, add2, add2, MINUS * token labels : - * rule labels : add2, add1, retval + * rule labels : add1, add2, retval * token list labels : * rule list labels : */ { + pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add1; pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add2; - pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add1; pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_retval; + stream_add1=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add1", add1.tree != NULL ? add1.tree : NULL); stream_add2=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add2", add2.tree != NULL ? add2.tree : NULL); - stream_add1=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add1", add1.tree != NULL ? add1.tree : NULL); stream_retval=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token retval", retval.tree != NULL ? retval.tree : NULL); root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -4735,8 +4735,8 @@ } retval.tree = root_0; // set result root + if (stream_add1 != NULL) stream_add1->free(stream_add1); if (stream_add2 != NULL) stream_add2->free(stream_add2); - if (stream_add1 != NULL) stream_add1->free(stream_add1); if (stream_retval != NULL) stream_retval->free(stream_retval); Modified: translator/pncompactor.g =================================================================== --- translator/pncompactor.g 2009-07-08 20:52:51 UTC (rev 192) +++ translator/pncompactor.g 2009-07-08 20:55:01 UTC (rev 193) @@ -24,7 +24,7 @@ #include <stdbool.h> #include "general.h" - #define DEBUG true + #define DEBUG false } @members { Modified: translator/pncompactor.h =================================================================== --- translator/pncompactor.h 2009-07-08 20:52:51 UTC (rev 192) +++ translator/pncompactor.h 2009-07-08 20:55:01 UTC (rev 193) @@ -2,7 +2,7 @@ * This C header file was generated by $ANTLR version 3.1.2 * * - From the grammar source file : /Users/bion/projects/iordache/translator/pncompactor.g - * - On : 2009-07-08 15:50:56 + * - On : 2009-07-08 15:54:37 * - for the tree parser : pncompactorTreeParser * * Editing it, at least manually, is not wise. * @@ -110,7 +110,7 @@ #include <stdbool.h> #include "general.h" - #define DEBUG true + #define DEBUG false #ifdef ANTLR3_WINDOWS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <the...@us...> - 2009-07-08 20:52:57
|
Revision: 192 http://pntool.svn.sourceforge.net/pntool/?rev=192&view=rev Author: thecodeweasel Date: 2009-07-08 20:52:51 +0000 (Wed, 08 Jul 2009) Log Message: ----------- Fixed distribution across subtraction Modified Paths: -------------- translator/pncompactor.c translator/pncompactor.g translator/pncompactor.h Modified: translator/pncompactor.c =================================================================== --- translator/pncompactor.c 2009-07-08 20:25:11 UTC (rev 191) +++ translator/pncompactor.c 2009-07-08 20:52:51 UTC (rev 192) @@ -2,7 +2,7 @@ * This C source file was generated by $ANTLR version 3.1.2 * * - From the grammar source file : /Users/bion/projects/iordache/translator/pncompactor.g - * - On : 2009-07-08 15:13:37 + * - On : 2009-07-08 15:50:56 * - for the tree parser : pncompactorTreeParser * * Editing it, at least manually, is not wise. * @@ -47,7 +47,7 @@ #include <stdbool.h> #include "general.h" - #define DEBUG false + #define DEBUG true /* End of Header action. * ============================================================================= @@ -3863,19 +3863,19 @@ /* AST REWRITE - * elements : EQ_OP, EQ_OP, EQ_OP, add2, add1, add1, EQ_OP, add1, add2, EQ_OP, EQ_OP, add2, add2, add1 + * elements : add1, add2, EQ_OP, add1, EQ_OP, EQ_OP, add2, EQ_OP, add1, EQ_OP, add1, add2, add2, EQ_OP * token labels : - * rule labels : add1, add2, retval + * rule labels : add2, add1, retval * token list labels : * rule list labels : */ { + pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add2; pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add1; - pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add2; pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_retval; + stream_add2=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add2", add2.tree != NULL ? add2.tree : NULL); stream_add1=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add1", add1.tree != NULL ? add1.tree : NULL); - stream_add2=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add2", add2.tree != NULL ? add2.tree : NULL); stream_retval=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token retval", retval.tree != NULL ? retval.tree : NULL); root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -4065,8 +4065,8 @@ } retval.tree = root_0; // set result root + if (stream_add2 != NULL) stream_add2->free(stream_add2); if (stream_add1 != NULL) stream_add1->free(stream_add1); - if (stream_add2 != NULL) stream_add2->free(stream_add2); if (stream_retval != NULL) stream_retval->free(stream_retval); @@ -4386,19 +4386,19 @@ /* AST REWRITE - * elements : add2, add1, add1, PLUS, add2, add1, PLUS, add2, add2 + * elements : add1, add2, add2, PLUS, add2, add1, PLUS, add2, add1 * token labels : - * rule labels : add1, add2, retval + * rule labels : add2, add1, retval * token list labels : * rule list labels : */ { + pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add2; pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add1; - pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_add2; pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream_retval; + stream_add2=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add2", add2.tree != NULL ? add2.tree : NULL); stream_add1=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add1", add1.tree != NULL ? add1.tree : NULL); - stream_add2=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token add2", add2.tree != NULL ? add2.tree : NULL); stream_retval=antlr3RewriteRuleSubtreeStreamNewAEE(ADAPTOR, RECOGNIZER, (pANTLR3_UINT8)"token retval", retval.tree != NULL ? retval.tree : NULL); root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -4511,8 +4511,8 @@ } retval.tree = root_0; // set result root + if (stream_add2 != NULL) stream_add2->free(stream_add2); if (stream_add1 != NULL) stream_add1->free(stream_add1); - if (stream_add2 != NULL) stream_add2->free(stream_add2); if (stream_retval != NULL) stream_retval->free(stream_retval); @@ -4560,6 +4560,13 @@ printf("-->%d : %d\n", *(int*) (SCOPE_TOP(constraints))->dist->peek( (SCOPE_TOP(constraints))->dist), (SCOPE_TOP(constraints))->dist->size( (SCOPE_TOP(constraints))->dist)); } flipped = true; + } else { + i = -i; + (SCOPE_TOP(constraints))->dist->push( (SCOPE_TOP(constraints))->dist, &i, NULL); + if(DEBUG) { + printf("-->%d : %d\n", *(int*) (SCOPE_TOP(constraints))->dist->peek( (SCOPE_TOP(constraints))->dist), (SCOPE_TOP(constraints))->dist->size( (SCOPE_TOP(constraints))->dist)); + } + flipped = true; } } @@ -4576,14 +4583,14 @@ CREATE_stream_additiveExpression; stream_additiveExpression->add(stream_additiveExpression, add2.tree, NULL); { + if(DEBUG) { + printf("<--%d : ", *(int*) (SCOPE_TOP(constraints))->dist->peek( (SCOPE_TOP(constraints))->dist)); + } + (SCOPE_TOP(constraints))->dist->pop( (SCOPE_TOP(constraints))->dist); + if(DEBUG) { + printf("%d\n", (SCOPE_TOP(constraints))->dist->size( (SCOPE_TOP(constraints))->dist)); + } if(flipped) { - if(DEBUG) { - printf("<--%d : ", *(int*) (SCOPE_TOP(constraints))->dist->peek( (SCOPE_TOP(constraints))->dist)); - } - (SCOPE_TOP(constraints))->dist->pop( (SCOPE_TOP(constraints))->dist); - if(DEBUG) { - printf("%d\n", (SCOPE_TOP(constraints))->dist->size( (SCOPE_TOP(constraints))->dist)); - } tok = ADAPTOR->createToken(ADAPTOR, PLUS, (pANTLR3_UINT8)"+"); } else { tok = ADAPTOR->createToken(ADAPTOR, MINUS, (pANTLR3_UINT8)"-"); @@ -4603,7 +4610,7 @@ /* AST REWRITE - * elements : add1, add1, add2, add2, MINUS, add2, add1, add2 + * elements : add1, add1, add2, MINUS, add2, add2, add1, add2 * token labels : * rule labels : add2, add1, retval * token list labels : @@ -4620,15 +4627,15 @@ root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); retval.tree = root_0; - // 225:9: -> {$add1.numeric && $add2.numeric}? + // 232:9: -> {$add1.numeric && $add2.numeric}? if (add1.numeric && add2.numeric) { root_0 = NULL; /* <-- rewriteEmptyAlt()) */ } - else // 226:7: -> {$add1.numeric && flipped}? ^( PLUS[tok, \"+\"] $add2) + else // 233:7: -> {$add1.numeric && flipped}? ^( PLUS[tok, \"+\"] $add2) if (add1.numeric && flipped) { - // /Users/bion/projects/iordache/translator/pncompactor.g:226:40: ^( PLUS[tok, \"+\"] $add2) + // /Users/bion/projects/iordache/translator/pncompactor.g:233:40: ^( PLUS[tok, \"+\"] $add2) { pANTLR3_BASE_TREE root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->becomeRoot(ADAPTOR, @@ -4645,10 +4652,10 @@ } } - else // 227:7: -> {$add1.numeric}? ^( MINUS[tok, \"-\"] $add2) + else // 234:7: -> {$add1.numeric}? ^( MINUS[tok, \"-\"] $add2) if (add1.numeric) { - // /Users/bion/projects/iordache/translator/pncompactor.g:227:32: ^( MINUS[tok, \"-\"] $add2) + // /Users/bion/projects/iordache/translator/pncompactor.g:234:32: ^( MINUS[tok, \"-\"] $add2) { pANTLR3_BASE_TREE root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->becomeRoot(ADAPTOR, @@ -4665,10 +4672,10 @@ } } - else // 228:7: -> {$add2.numeric}? ^( PLUS[tok, \"+\"] $add1) + else // 235:7: -> {$add2.numeric}? ^( PLUS[tok, \"+\"] $add1) if (add2.numeric) { - // /Users/bion/projects/iordache/translator/pncompactor.g:228:32: ^( PLUS[tok, \"+\"] $add1) + // /Users/bion/projects/iordache/translator/pncompactor.g:235:32: ^( PLUS[tok, \"+\"] $add1) { pANTLR3_BASE_TREE root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->becomeRoot(ADAPTOR, @@ -4685,10 +4692,10 @@ } } - else // 229:7: -> {flipped}? ^( ADD[tok, \"+\"] $add1 $add2) + else // 236:7: -> {flipped}? ^( ADD[tok, \"+\"] $add1 $add2) if (flipped) { - // /Users/bion/projects/iordache/translator/pncompactor.g:229:28: ^( ADD[tok, \"+\"] $add1 $add2) + // /Users/bion/projects/iordache/translator/pncompactor.g:236:28: ^( ADD[tok, \"+\"] $add1 $add2) { pANTLR3_BASE_TREE root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->becomeRoot(ADAPTOR, @@ -4706,9 +4713,9 @@ } } - else // 230:7: -> ^( SUB[tok, \"-\"] $add1 $add2) + else // 237:7: -> ^( SUB[tok, \"-\"] $add1 $add2) { - // /Users/bion/projects/iordache/translator/pncompactor.g:230:21: ^( SUB[tok, \"-\"] $add1 $add2) + // /Users/bion/projects/iordache/translator/pncompactor.g:237:21: ^( SUB[tok, \"-\"] $add1 $add2) { pANTLR3_BASE_TREE root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->becomeRoot(ADAPTOR, @@ -4764,7 +4771,7 @@ /** * $ANTLR start primary - * /Users/bion/projects/iordache/translator/pncompactor.g:231:1: primary[bool enableAlt] returns [int num, bool numeric] : ( ^( SUB additiveExpression[true] ) -> additiveExpression | group_elements -> {!enableAlt || i == 1}? group_elements -> ^( MULT[tok2, newVal2] NUM[tok, newVal] group_elements ) | number -> | ^( MULT number additiveExpression[false] ) -> {$number.value == 0}? -> additiveExpression ); + * /Users/bion/projects/iordache/translator/pncompactor.g:238:1: primary[bool enableAlt] returns [int num, bool numeric] : ( ^( SUB additiveExpression[true] ) -> additiveExpression | group_elements -> {!enableAlt || i == 1}? group_elements -> ^( MULT[tok2, newVal2] NUM[tok, newVal] group_elements ) | number -> | ^( MULT number additiveExpression[false] ) -> {$number.value == 0}? -> additiveExpression ); */ static pncompactor_primary_return primary(ppncompactor ctx, bool enableAlt) @@ -4856,7 +4863,7 @@ retval.tree = NULL; { { - // /Users/bion/projects/iordache/translator/pncompactor.g:241:5: ( ^( SUB additiveExpression[true] ) -> additiveExpression | group_elements -> {!enableAlt || i == 1}? group_elements -> ^( MULT[tok2, newVal2] NUM[tok, newVal] group_elements ) | number -> | ^( MULT number additiveExpression[false] ) -> {$number.value == 0}? -> additiveExpression ) + // /Users/bion/projects/iordache/translator/pncompactor.g:248:5: ( ^( SUB additiveExpression[true] ) -> additiveExpression | group_elements -> {!enableAlt || i == 1}? group_elements -> ^( MULT[tok2, newVal2] NUM[tok, newVal] group_elements ) | number -> | ^( MULT number additiveExpression[false] ) -> {$number.value == 0}? -> additiveExpression ) ANTLR3_UINT32 alt24; @@ -4900,7 +4907,7 @@ switch (alt24) { case 1: - // /Users/bion/projects/iordache/translator/pncompactor.g:241:9: ^( SUB additiveExpression[true] ) + // /Users/bion/projects/iordache/translator/pncompactor.g:248:9: ^( SUB additiveExpression[true] ) { _last = (pANTLR3_BASE_TREE)LT(1); { @@ -4971,7 +4978,7 @@ root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); retval.tree = root_0; - // 255:9: -> additiveExpression + // 262:9: -> additiveExpression { ADAPTOR->addChild(ADAPTOR, root_0, stream_additiveExpression == NULL ? NULL : stream_additiveExpression->nextTree(stream_additiveExpression)); @@ -4985,7 +4992,7 @@ } break; case 2: - // /Users/bion/projects/iordache/translator/pncompactor.g:256:7: group_elements + // /Users/bion/projects/iordache/translator/pncompactor.g:263:7: group_elements { _last = (pANTLR3_BASE_TREE)LT(1); FOLLOWPUSH(FOLLOW_group_elements_in_primary977); @@ -5026,15 +5033,15 @@ root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); retval.tree = root_0; - // 265:8: -> {!enableAlt || i == 1}? group_elements + // 272:8: -> {!enableAlt || i == 1}? group_elements if (!enableAlt || i == 1) { ADAPTOR->addChild(ADAPTOR, root_0, stream_group_elements == NULL ? NULL : stream_group_elements->nextTree(stream_group_elements)); } - else // 266:8: -> ^( MULT[tok2, newVal2] NUM[tok, newVal] group_elements ) + else // 273:8: -> ^( MULT[tok2, newVal2] NUM[tok, newVal] group_elements ) { - // /Users/bion/projects/iordache/translator/pncompactor.g:266:16: ^( MULT[tok2, newVal2] NUM[tok, newVal] group_elements ) + // /Users/bion/projects/iordache/translator/pncompactor.g:273:16: ^( MULT[tok2, newVal2] NUM[tok, newVal] group_elements ) { pANTLR3_BASE_TREE root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); root_1 = (pANTLR3_BASE_TREE)(ADAPTOR->becomeRoot(ADAPTOR, @@ -5067,7 +5074,7 @@ } break; case 3: - // /Users/bion/projects/iordache/translator/pncompactor.g:267:7: number + // /Users/bion/projects/iordache/translator/pncompactor.g:274:7: number { _last = (pANTLR3_BASE_TREE)LT(1); FOLLOWPUSH(FOLLOW_number_in_primary1017); @@ -5103,7 +5110,7 @@ root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); retval.tree = root_0; - // 271:8: -> + // 278:8: -> { root_0 = NULL; /* <-- rewriteEmptyAlt()) */ } @@ -5116,7 +5123,7 @@ } break; case 4: - // /Users/bion/projects/iordache/translator/pncompactor.g:272:7: ^( MULT number additiveExpression[false] ) + // /Users/bion/projects/iordache/translator/pncompactor.g:279:7: ^( MULT number additiveExpression[false] ) { _last = (pANTLR3_BASE_TREE)LT(1); { @@ -5199,12 +5206,12 @@ root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); retval.tree = root_0; - // 287:8: -> {$number.value == 0}? + // 294:8: -> {$number.value == 0}? if (number57.value == 0) { root_0 = NULL; /* <-- rewriteEmptyAlt()) */ } - else // 288:7: -> additiveExpression + else // 295:7: -> additiveExpression { ADAPTOR->addChild(ADAPTOR, root_0, stream_additiveExpression == NULL ? NULL : stream_additiveExpression->nextTree(stream_additiveExpression)); @@ -5247,7 +5254,7 @@ /** * $ANTLR start live_def - * /Users/bion/projects/iordache/translator/pncompactor.g:289:1: live_def : ( ^( LIVE ALL ( ID )* ) | ^( LIVE ( ID )+ ) ); + * /Users/bion/projects/iordache/translator/pncompactor.g:296:1: live_def : ( ^( LIVE ALL ( ID )* ) | ^( LIVE ( ID )+ ) ); */ static pncompactor_live_def_return live_def(ppncompactor ctx) @@ -5299,7 +5306,7 @@ retval.tree = NULL; { { - // /Users/bion/projects/iordache/translator/pncompactor.g:290:2: ( ^( LIVE ALL ( ID )* ) | ^( LIVE ( ID )+ ) ) + // /Users/bion/projects/iordache/translator/pncompactor.g:297:2: ( ^( LIVE ALL ( ID )* ) | ^( LIVE ( ID )+ ) ) ANTLR3_UINT32 alt27; @@ -5370,7 +5377,7 @@ switch (alt27) { case 1: - // /Users/bion/projects/iordache/translator/pncompactor.g:290:4: ^( LIVE ALL ( ID )* ) + // /Users/bion/projects/iordache/translator/pncompactor.g:297:4: ^( LIVE ALL ( ID )* ) { root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -5404,7 +5411,7 @@ ALL60_tree = (pANTLR3_BASE_TREE)ADAPTOR->dupNode(ADAPTOR, ALL60);ADAPTOR->addChild(ADAPTOR, root_1, ALL60_tree); - // /Users/bion/projects/iordache/translator/pncompactor.g:290:15: ( ID )* + // /Users/bion/projects/iordache/translator/pncompactor.g:297:15: ( ID )* for (;;) { @@ -5422,7 +5429,7 @@ switch (alt25) { case 1: - // /Users/bion/projects/iordache/translator/pncompactor.g:290:15: ID + // /Users/bion/projects/iordache/translator/pncompactor.g:297:15: ID { _last = (pANTLR3_BASE_TREE)LT(1); ID61 = (pANTLR3_BASE_TREE) MATCHT(ID, &FOLLOW_ID_in_live_def1068); @@ -5452,7 +5459,7 @@ } break; case 2: - // /Users/bion/projects/iordache/translator/pncompactor.g:291:4: ^( LIVE ( ID )+ ) + // /Users/bion/projects/iordache/translator/pncompactor.g:298:4: ^( LIVE ( ID )+ ) { root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -5476,7 +5483,7 @@ MATCHT(ANTLR3_TOKEN_DOWN, NULL); - // /Users/bion/projects/iordache/translator/pncompactor.g:291:11: ( ID )+ + // /Users/bion/projects/iordache/translator/pncompactor.g:298:11: ( ID )+ { int cnt26=0; @@ -5496,7 +5503,7 @@ switch (alt26) { case 1: - // /Users/bion/projects/iordache/translator/pncompactor.g:291:11: ID + // /Users/bion/projects/iordache/translator/pncompactor.g:298:11: ID { _last = (pANTLR3_BASE_TREE)LT(1); ID63 = (pANTLR3_BASE_TREE) MATCHT(ID, &FOLLOW_ID_in_live_def1078); @@ -5564,7 +5571,7 @@ /** * $ANTLR start uncontrol - * /Users/bion/projects/iordache/translator/pncompactor.g:292:1: uncontrol : ^( UNCONTROL ( ID )+ ) ; + * /Users/bion/projects/iordache/translator/pncompactor.g:299:1: uncontrol : ^( UNCONTROL ( ID )+ ) ; */ static pncompactor_uncontrol_return uncontrol(ppncompactor ctx) @@ -5603,8 +5610,8 @@ retval.tree = NULL; { - // /Users/bion/projects/iordache/translator/pncompactor.g:293:2: ( ^( UNCONTROL ( ID )+ ) ) - // /Users/bion/projects/iordache/translator/pncompactor.g:293:4: ^( UNCONTROL ( ID )+ ) + // /Users/bion/projects/iordache/translator/pncompactor.g:300:2: ( ^( UNCONTROL ( ID )+ ) ) + // /Users/bion/projects/iordache/translator/pncompactor.g:300:4: ^( UNCONTROL ( ID )+ ) { root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -5628,7 +5635,7 @@ MATCHT(ANTLR3_TOKEN_DOWN, NULL); - // /Users/bion/projects/iordache/translator/pncompactor.g:293:16: ( ID )+ + // /Users/bion/projects/iordache/translator/pncompactor.g:300:16: ( ID )+ { int cnt28=0; @@ -5648,7 +5655,7 @@ switch (alt28) { case 1: - // /Users/bion/projects/iordache/translator/pncompactor.g:293:16: ID + // /Users/bion/projects/iordache/translator/pncompactor.g:300:16: ID { _last = (pANTLR3_BASE_TREE)LT(1); ID65 = (pANTLR3_BASE_TREE) MATCHT(ID, &FOLLOW_ID_in_uncontrol1092); @@ -5713,7 +5720,7 @@ /** * $ANTLR start unobserve - * /Users/bion/projects/iordache/translator/pncompactor.g:294:1: unobserve : ^( UNOBSERVE ( ID )+ ) ; + * /Users/bion/projects/iordache/translator/pncompactor.g:301:1: unobserve : ^( UNOBSERVE ( ID )+ ) ; */ static pncompactor_unobserve_return unobserve(ppncompactor ctx) @@ -5752,8 +5759,8 @@ retval.tree = NULL; { - // /Users/bion/projects/iordache/translator/pncompactor.g:295:2: ( ^( UNOBSERVE ( ID )+ ) ) - // /Users/bion/projects/iordache/translator/pncompactor.g:295:4: ^( UNOBSERVE ( ID )+ ) + // /Users/bion/projects/iordache/translator/pncompactor.g:302:2: ( ^( UNOBSERVE ( ID )+ ) ) + // /Users/bion/projects/iordache/translator/pncompactor.g:302:4: ^( UNOBSERVE ( ID )+ ) { root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -5777,7 +5784,7 @@ MATCHT(ANTLR3_TOKEN_DOWN, NULL); - // /Users/bion/projects/iordache/translator/pncompactor.g:295:16: ( ID )+ + // /Users/bion/projects/iordache/translator/pncompactor.g:302:16: ( ID )+ { int cnt29=0; @@ -5797,7 +5804,7 @@ switch (alt29) { case 1: - // /Users/bion/projects/iordache/translator/pncompactor.g:295:16: ID + // /Users/bion/projects/iordache/translator/pncompactor.g:302:16: ID { _last = (pANTLR3_BASE_TREE)LT(1); ID67 = (pANTLR3_BASE_TREE) MATCHT(ID, &FOLLOW_ID_in_unobserve1106); @@ -5862,7 +5869,7 @@ /** * $ANTLR start other_commands - * /Users/bion/projects/iordache/translator/pncompactor.g:297:1: other_commands : print ; + * /Users/bion/projects/iordache/translator/pncompactor.g:304:1: other_commands : print ; */ static pncompactor_other_commands_return other_commands(ppncompactor ctx) @@ -5898,8 +5905,8 @@ retval.tree = NULL; { - // /Users/bion/projects/iordache/translator/pncompactor.g:298:2: ( print ) - // /Users/bion/projects/iordache/translator/pncompactor.g:298:4: print + // /Users/bion/projects/iordache/translator/pncompactor.g:305:2: ( print ) + // /Users/bion/projects/iordache/translator/pncompactor.g:305:4: print { root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -5941,7 +5948,7 @@ /** * $ANTLR start print - * /Users/bion/projects/iordache/translator/pncompactor.g:299:1: print : ^( PRINT ID group_elements ) ; + * /Users/bion/projects/iordache/translator/pncompactor.g:306:1: print : ^( PRINT ID group_elements ) ; */ static pncompactor_print_return print(ppncompactor ctx) @@ -5985,8 +5992,8 @@ retval.tree = NULL; { - // /Users/bion/projects/iordache/translator/pncompactor.g:300:2: ( ^( PRINT ID group_elements ) ) - // /Users/bion/projects/iordache/translator/pncompactor.g:300:4: ^( PRINT ID group_elements ) + // /Users/bion/projects/iordache/translator/pncompactor.g:307:2: ( ^( PRINT ID group_elements ) ) + // /Users/bion/projects/iordache/translator/pncompactor.g:307:4: ^( PRINT ID group_elements ) { root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -6061,7 +6068,7 @@ /** * $ANTLR start number - * /Users/bion/projects/iordache/translator/pncompactor.g:302:1: number returns [int value] : ( INT -> NUM[tok, newVal] | ^( MINUS INT ) -> NUM[tok, newVal] ); + * /Users/bion/projects/iordache/translator/pncompactor.g:309:1: number returns [int value] : ( INT -> NUM[tok, newVal] | ^( MINUS INT ) -> NUM[tok, newVal] ); */ static pncompactor_number_return number(ppncompactor ctx) @@ -6117,7 +6124,7 @@ retval.tree = NULL; { { - // /Users/bion/projects/iordache/translator/pncompactor.g:309:2: ( INT -> NUM[tok, newVal] | ^( MINUS INT ) -> NUM[tok, newVal] ) + // /Users/bion/projects/iordache/translator/pncompactor.g:316:2: ( INT -> NUM[tok, newVal] | ^( MINUS INT ) -> NUM[tok, newVal] ) ANTLR3_UINT32 alt30; @@ -6150,7 +6157,7 @@ switch (alt30) { case 1: - // /Users/bion/projects/iordache/translator/pncompactor.g:309:4: INT + // /Users/bion/projects/iordache/translator/pncompactor.g:316:4: INT { _last = (pANTLR3_BASE_TREE)LT(1); INT72 = (pANTLR3_BASE_TREE) MATCHT(INT, &FOLLOW_INT_in_number1151); @@ -6190,7 +6197,7 @@ root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); retval.tree = root_0; - // 319:5: -> NUM[tok, newVal] + // 326:5: -> NUM[tok, newVal] { ADAPTOR->addChild(ADAPTOR, root_0, #if 2 == 2 @@ -6210,7 +6217,7 @@ } break; case 2: - // /Users/bion/projects/iordache/translator/pncompactor.g:320:4: ^( MINUS INT ) + // /Users/bion/projects/iordache/translator/pncompactor.g:327:4: ^( MINUS INT ) { _last = (pANTLR3_BASE_TREE)LT(1); { @@ -6269,7 +6276,7 @@ root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); retval.tree = root_0; - // 327:5: -> NUM[tok, newVal] + // 334:5: -> NUM[tok, newVal] { ADAPTOR->addChild(ADAPTOR, root_0, #if 2 == 2 @@ -6316,7 +6323,7 @@ /** * $ANTLR start group_elements - * /Users/bion/projects/iordache/translator/pncompactor.g:328:1: group_elements : ^( GROUP ( ID )+ ) ; + * /Users/bion/projects/iordache/translator/pncompactor.g:335:1: group_elements : ^( GROUP ( ID )+ ) ; */ static pncompactor_group_elements_return group_elements(ppncompactor ctx) @@ -6355,8 +6362,8 @@ retval.tree = NULL; { - // /Users/bion/projects/iordache/translator/pncompactor.g:329:2: ( ^( GROUP ( ID )+ ) ) - // /Users/bion/projects/iordache/translator/pncompactor.g:329:4: ^( GROUP ( ID )+ ) + // /Users/bion/projects/iordache/translator/pncompactor.g:336:2: ( ^( GROUP ( ID )+ ) ) + // /Users/bion/projects/iordache/translator/pncompactor.g:336:4: ^( GROUP ( ID )+ ) { root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -6380,7 +6387,7 @@ MATCHT(ANTLR3_TOKEN_DOWN, NULL); - // /Users/bion/projects/iordache/translator/pncompactor.g:329:12: ( ID )+ + // /Users/bion/projects/iordache/translator/pncompactor.g:336:12: ( ID )+ { int cnt31=0; @@ -6400,7 +6407,7 @@ switch (alt31) { case 1: - // /Users/bion/projects/iordache/translator/pncompactor.g:329:12: ID + // /Users/bion/projects/iordache/translator/pncompactor.g:336:12: ID { _last = (pANTLR3_BASE_TREE)LT(1); ID76 = (pANTLR3_BASE_TREE) MATCHT(ID, &FOLLOW_ID_in_group_elements1186); @@ -6465,7 +6472,7 @@ /** * $ANTLR start numbered_ID - * /Users/bion/projects/iordache/translator/pncompactor.g:330:1: numbered_ID : ( ID | ^( ID INT ) ); + * /Users/bion/projects/iordache/translator/pncompactor.g:337:1: numbered_ID : ( ID | ^( ID INT ) ); */ static pncompactor_numbered_ID_return numbered_ID(ppncompactor ctx) @@ -6509,7 +6516,7 @@ retval.tree = NULL; { { - // /Users/bion/projects/iordache/translator/pncompactor.g:331:2: ( ID | ^( ID INT ) ) + // /Users/bion/projects/iordache/translator/pncompactor.g:338:2: ( ID | ^( ID INT ) ) ANTLR3_UINT32 alt32; @@ -6561,7 +6568,7 @@ switch (alt32) { case 1: - // /Users/bion/projects/iordache/translator/pncompactor.g:331:4: ID + // /Users/bion/projects/iordache/translator/pncompactor.g:338:4: ID { root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); @@ -6578,7 +6585,7 @@ } break; case 2: - // /Users/bion/projects/iordache/translator/pncompactor.g:332:4: ^( ID INT ) + // /Users/bion/projects/iordache/translator/pncompactor.g:339:4: ^( ID INT ) { root_0 = (pANTLR3_BASE_TREE)(ADAPTOR->nilNode(ADAPTOR)); Modified: translator/pncompactor.g =================================================================== --- translator/pncompactor.g 2009-07-08 20:25:11 UTC (rev 191) +++ translator/pncompactor.g 2009-07-08 20:52:51 UTC (rev 192) @@ -24,7 +24,7 @@ #include <stdbool.h> #include "general.h" - #define DEBUG false + #define DEBUG true } @members { @@ -201,17 +201,24 @@ printf("-->\%d : \%d\n", *(int*)$constraints::dist->peek($constraints::dist), $constraints::dist->size($constraints::dist)); } flipped = true; + } else { + i = -i; + $constraints::dist->push($constraints::dist, &i, NULL); + if(DEBUG) { + printf("-->\%d : \%d\n", *(int*)$constraints::dist->peek($constraints::dist), $constraints::dist->size($constraints::dist)); + } + flipped = true; } } add2=additiveExpression[true] { + if(DEBUG) { + printf("<--\%d : ", *(int*)$constraints::dist->peek($constraints::dist)); + } + $constraints::dist->pop($constraints::dist); + if(DEBUG) { + printf("\%d\n", $constraints::dist->size($constraints::dist)); + } if(flipped) { - if(DEBUG) { - printf("<--\%d : ", *(int*)$constraints::dist->peek($constraints::dist)); - } - $constraints::dist->pop($constraints::dist); - if(DEBUG) { - printf("\%d\n", $constraints::dist->size($constraints::dist)); - } tok = ADAPTOR->createToken(ADAPTOR, PLUS, (pANTLR3_UINT8)"+"); } else { tok = ADAPTOR->createToken(ADAPTOR, MINUS, (pANTLR3_UINT8)"-"); Modified: translator/pncompactor.h =================================================================== --- translator/pncompactor.h 2009-07-08 20:25:11 UTC (rev 191) +++ translator/pncompactor.h 2009-07-08 20:52:51 UTC (rev 192) @@ -2,7 +2,7 @@ * This C header file was generated by $ANTLR version 3.1.2 * * - From the grammar source file : /Users/bion/projects/iordache/translator/pncompactor.g - * - On : 2009-07-08 15:13:37 + * - On : 2009-07-08 15:50:56 * - for the tree parser : pncompactorTreeParser * * Editing it, at least manually, is not wise. * @@ -110,7 +110,7 @@ #include <stdbool.h> #include "general.h" - #define DEBUG false + #define DEBUG true #ifdef ANTLR3_WINDOWS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |