[Pntool-developers] SF.net SVN: pntool:[246]
Brought to you by:
compaqdrew,
miordache
From: <mio...@us...> - 2011-04-08 22:36:53
|
Revision: 246 http://pntool.svn.sourceforge.net/pntool/?rev=246&view=rev Author: miordache Date: 2011-04-08 22:36:44 +0000 (Fri, 08 Apr 2011) Log Message: ----------- update Modified Paths: -------------- 2009_version/codegen/Makefile Makefile newcodegen/Makefile pnheaders/insert.c Added Paths: ----------- 2009_version/ 2009_version/Makefile09 2009_version/codegen/ 2009_version/pnheaders/ 2009_version/spnbox09/ 2009_version/spnbox09/Makefile 2009_version/spnbox09/MemoryManager.c 2009_version/spnbox09/MemoryManager.h 2009_version/spnbox09/actn.c 2009_version/spnbox09/admcon.c 2009_version/spnbox09/asiph.c 2009_version/spnbox09/avpr.c 2009_version/spnbox09/chkcons.c 2009_version/spnbox09/deallocation.c 2009_version/spnbox09/dp.c 2009_version/spnbox09/dp4.c 2009_version/spnbox09/extendedmatrix.c 2009_version/spnbox09/extendedmatrix.h 2009_version/spnbox09/fvpr.c 2009_version/spnbox09/gcdv.c 2009_version/spnbox09/ilpadm.c 2009_version/spnbox09/invar.c 2009_version/spnbox09/ipslv.c 2009_version/spnbox09/ipsolve.c 2009_version/spnbox09/isadm.c 2009_version/spnbox09/issiph.c 2009_version/spnbox09/linenf.c 2009_version/spnbox09/matrixmath.c 2009_version/spnbox09/matrixmath.h 2009_version/spnbox09/mroadm.c 2009_version/spnbox09/msplit.c 2009_version/spnbox09/nltrans.c 2009_version/spnbox09/pn2acpn.c 2009_version/spnbox09/pn2eacpn.c 2009_version/spnbox09/reduce.c 2009_version/spnbox09/spnbox.h 2009_version/spnbox09/supervis.c 2009_version/spnbox09/tactn.c 2009_version/spnbox09/tests/ 2009_version/spnbox09/tests/Makefile 2009_version/spnbox09/tests/StructuredIO.c 2009_version/spnbox09/tests/StructuredIO.h 2009_version/spnbox09/tests/pnexample.c 2009_version/spnbox09/tests/test-actn.c 2009_version/spnbox09/tests/test-actn.txt 2009_version/spnbox09/tests/test-admcon.c 2009_version/spnbox09/tests/test-asiph.c 2009_version/spnbox09/tests/test-asiph.txt 2009_version/spnbox09/tests/test-avpr.c 2009_version/spnbox09/tests/test-avpr.txt 2009_version/spnbox09/tests/test-dp.c 2009_version/spnbox09/tests/test-dp.txt 2009_version/spnbox09/tests/test-extendedmatrix.c 2009_version/spnbox09/tests/test-extendedmatrix.txt 2009_version/spnbox09/tests/test-fvpr.c 2009_version/spnbox09/tests/test-fvpr.txt 2009_version/spnbox09/tests/test-gcdv.c 2009_version/spnbox09/tests/test-gcdv.txt 2009_version/spnbox09/tests/test-ilpadm.c 2009_version/spnbox09/tests/test-ilpadm.txt 2009_version/spnbox09/tests/test-invar.c 2009_version/spnbox09/tests/test-invar.txt 2009_version/spnbox09/tests/test-ipslv.c 2009_version/spnbox09/tests/test-ipsolve.c 2009_version/spnbox09/tests/test-ipsolve.txt 2009_version/spnbox09/tests/test-isadm.c 2009_version/spnbox09/tests/test-isadm.txt 2009_version/spnbox09/tests/test-issiph.c 2009_version/spnbox09/tests/test-issiph.txt 2009_version/spnbox09/tests/test-linenf.c 2009_version/spnbox09/tests/test-linenf.txt 2009_version/spnbox09/tests/test-matrixmath.c 2009_version/spnbox09/tests/test-matrixmath.txt 2009_version/spnbox09/tests/test-mroadm.c 2009_version/spnbox09/tests/test-mroadm.txt 2009_version/spnbox09/tests/test-msplit.c 2009_version/spnbox09/tests/test-msplit.txt 2009_version/spnbox09/tests/test-nltrans.c 2009_version/spnbox09/tests/test-nltrans.txt 2009_version/spnbox09/tests/test-pn2acpn.c 2009_version/spnbox09/tests/test-pn2acpn.txt 2009_version/spnbox09/tests/test-pn2eacpn.c 2009_version/spnbox09/tests/test-pn2eacpn.txt 2009_version/spnbox09/tests/test-reduce.c 2009_version/spnbox09/tests/test-reduce.txt 2009_version/spnbox09/tests/test-supervis.c 2009_version/spnbox09/tests/test-supervis.txt 2009_version/spnbox09/tests/test-tactn.c 2009_version/spnbox09/tests/test-tactn.txt 2009_version/spnbox09/tests/test.c 2009_version/spnbox09/tests/test.h LICENSE/ LICENSE/ANTLR3_LICENSE.txt LICENSE/LICENSE.txt LICENSE/README.txt README.txt pnheaders/Makefile Removed Paths: ------------- ANTLR3_LICENSE.txt LICENSE.txt Makefile09 codegen/ pnheaders09/ Copied: 2009_version/Makefile09 (from rev 245, Makefile09) =================================================================== --- 2009_version/Makefile09 (rev 0) +++ 2009_version/Makefile09 2011-04-08 22:36:44 UTC (rev 246) @@ -0,0 +1,34 @@ +# This is the make file of the 2009 version of the program. + +COMPILER=gcc -g + +PNHEADERS=pnheaders +SPNBOX=spnbox09 +CODEGEN=codegen +CODEGENOBJS = codegen/src +TRANSLATOR=../translator + +ct09: objectfiles main_function.o + $(COMPILER) -o ct09 $(PNHEADERS)/*.o $(CODEGENOBJS)/*.o $(SPNBOX)/*.o \ + main_function.o $(SPNBOX)/*.a $(TRANSLATOR)/libtranslator.a + +objectfiles: + cd $(PNHEADERS); make + cd $(CODEGEN); make static + cd $(SPNBOX); make + cd $(TRANSLATOR); make + +main_function.o: $(PNHEADERS)/main_function.c $(PNHEADERS)/pns.h $(SPNBOX)/spnbox.h $(CODEGEN)/src/codegen.h + $(COMPILER) -c $(PNHEADERS)/main_function.c -Ispnbox09 -I$(CODEGEN)/src -I$(PNHEADERS) + +clean: + rm -f main_function.o + cd $(PNHEADERS); make clean + cd codegen; make clean + cd $(TRANSLATOR); make clean + cd $(SPNBOX); make clean + +distclean: clean + cd codegen; make distclean + cd $(TRANSLATOR); make distclean + Modified: 2009_version/codegen/Makefile =================================================================== --- codegen/Makefile 2011-04-02 00:10:24 UTC (rev 245) +++ 2009_version/codegen/Makefile 2011-04-08 22:36:44 UTC (rev 246) @@ -2,7 +2,8 @@ COMPILER=gcc -g -PNHEADERS = ../pnheaders/general.o ../pnheaders/matrix.o ../pnheaders/pns.o +PNHEADERS = ../pnheaders/general.c ../pnheaders/matrix.c ../pnheaders/pns.c +PNOBJS = ../pnheaders/general.o ../pnheaders/matrix.o ../pnheaders/pns.o STANDALONE = src/main.o OBJS = src/codegen.o src/plantCompiler.o src/supervisorCompiler.o src/petriNetSerializer.o src/text.o src/MakeGen.o B = \033[32m @@ -10,21 +11,21 @@ -standalone: pnslib static $(STANDALONE) +standalone: pnslib static $(STANDALONE) $(PNOBJS) echo "$(B)Making standalone files...$(E)" $(COMPILER) -c $(STANDALONE) echo "$(B)Linking it all up...$(E)" - $(COMPILER) -o codegen $(OBJS) $(PNHEADERS) $(STANDALONE) + $(COMPILER) -o codegen $(OBJS) $(PNOBJS) $(STANDALONE) echo "$(B)Done$(E)" -pnslib: $(PNHEADERS) +pnslib: $(PNHEADERS) echo "$(B) Precompiling pnheaders...$(E)" $(COMPILER) -c $(PNHEADERS) echo "$(B)Done$(E)" static: $(OBJS) pnslib echo "$(B) Making pure codegen...$(E)" - $(COMPILER) -c $(OBJS) $(PNHEADERS) -I../pnheaders + #$(COMPILER) -c $(OBJS) -I../pnheaders echo "$(B)Done$(E)" src/%.o : src/%.c $(COMPILER) -I../pnheaders -o src/$*.o -c src/$*.c @@ -41,6 +42,6 @@ echo "$(B)Done$(E)" distclean: clean echo "$(B)Making distclean...$(E)" - rm -f $(PNHEADERS) + rm -f $(PNOBJS) echo "$(B)Done$(E)" Added: 2009_version/spnbox09/Makefile =================================================================== --- 2009_version/spnbox09/Makefile (rev 0) +++ 2009_version/spnbox09/Makefile 2011-04-08 22:36:44 UTC (rev 246) @@ -0,0 +1,108 @@ +#This is the makefile for all spnbox functions. +#It is called by the pntool makefile to create object code for all the functions. + +COMPILER=gcc -g +PNHEADERS=../pnheaders + +all: actn.o admcon.o asiph.o avpr.o chkcons.o deallocation.o dp.o\ + extendedmatrix.o fvpr.o gcdv.o invar.o ilpadm.o ipslv.o ipsolve.o isadm.o\ + issiph.o linenf.o matrixmath.o MemoryManager.o mroadm.o msplit.o nltrans.o\ + pn2acpn.o pn2eacpn.o reduce.o supervis.o tactn.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 + +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 + $(COMPILER) -c chkcons.c + +deallocation.o: deallocation.c spnbox.h $(PNHEADERS)/matrix.h + $(COMPILER) -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 + +dp4.o: dp4.c spnbox.h matrixmath.h extendedmatrix.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h $(PNHEADERS)/pns.h + $(COMPILER) -c dp4.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 + +gcdv.o: gcdv.c $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h + $(COMPILER) -c gcdv.c + +invar.o: invar.c spnbox.h matrixmath.h MemoryManager.h extendedmatrix.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h + $(COMPILER) -c invar.c + +ilpadm.o: ilpadm.c spnbox.h MemoryManager.h matrixmath.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h $(PNHEADERS)/pns.h + $(COMPILER) -c ilpadm.c + +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 + +matrixmath.o: matrixmath.c matrixmath.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h + $(COMPILER) -c matrixmath.c + +MemoryManager.o: MemoryManager.c MemoryManager.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h + $(COMPILER) -c MemoryManager.c + +mroadm.o: mroadm.c spnbox.h $(PNHEADERS)/matrix.h $(PNHEADERS)/general.h matrixmath.h + $(COMPILER) -c mroadm.c + +msplit.o: msplit.c spnbox.h MemoryManager.h matrixmath.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h + $(COMPILER) -c msplit.c + +nltrans.o: nltrans.c spnbox.h MemoryManager.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h + $(COMPILER) -c nltrans.c + +pn2acpn.o: pn2acpn.c spnbox.h MemoryManager.h matrixmath.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h + $(COMPILER) -c pn2acpn.c + +pn2eacpn.o: pn2eacpn.c spnbox.h MemoryManager.h matrixmath.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h + $(COMPILER) -c pn2eacpn.c + +reduce.o: reduce.c spnbox.h $(PNHEADERS)/general.h $(PNHEADERS)/matrix.h $(PNHEADERS)/pns.h + $(COMPILER) -c reduce.c + +supervis.o: supervis.c spnbox.h matrixmath.h $(PNHEADERS)/matrix.h + $(COMPILER) -c supervis.c + +tactn.o: tactn.c spnbox.h $(PNHEADERS)/matrix.h $(PNHEADERS)/pns.h matrixmath.h MemoryManager.h + $(COMPILER) -c tactn.c + +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 + +clean: + rm -fv *.o *.a + cd ../../third-party/lp_solve_5.5; make -f Makefile.Linux clean + +clean-partial: + rm -fv *.o + Added: 2009_version/spnbox09/MemoryManager.c =================================================================== --- 2009_version/spnbox09/MemoryManager.c (rev 0) +++ 2009_version/spnbox09/MemoryManager.c 2011-04-08 22:36:44 UTC (rev 246) @@ -0,0 +1,201 @@ +#include "MemoryManager.h" + +inline void ManageMatrix(MemoryManager* mgr, matrix* m) +{ + matrix **matrices; + if(mgr->nextm == mgr->lengthm) + { + if (! (matrices = realloc(mgr->matrices, sizeof(matrix*) * (mgr->lengthm + mgr->addressblockm)))) + { + merror(0, "Out of memory"); + return; + } + mgr->matrices = matrices; + mgr->lengthm += mgr->addressblockm; + } + mgr->matrices[mgr->nextm++] = m; +} + +inline void ManageMemory(MemoryManager* mgr, void* mem) +{ + void** memory; + if (mgr->next == mgr->length) + { + if (! (memory = realloc(mgr->memory, sizeof(void*) * (mgr->length + mgr->addressblock)))) + { + merror(0, "Out of memory"); + return; + } + mgr->memory = memory; + mgr->length += mgr->addressblock; + } + mgr->memory[mgr->next++] = mem; +} + +inline void* mmalloc(MemoryManager* mgr, size_t nbytes) +{ + void **memory; + if(mgr->next == mgr->length) + { + if (! (memory = realloc(mgr->memory, sizeof(void*) * (mgr->length + mgr->addressblock)))) + { + merror(0, "Out of memory"); + return; + } + mgr->memory = memory; + mgr->length += mgr->addressblock; + } + return mgr->memory[mgr->next++] = tmalloc(nbytes); +} + +inline void* mcalloc(MemoryManager* mgr, size_t n, size_t nbytes) +{ + void **memory; + if(mgr->next == mgr->length) + { + if (! (memory = realloc(mgr->memory, sizeof(void*) * (mgr->length + mgr->addressblock)))) + { + merror(0, "Out of memory"); + return; + } + mgr->memory = memory; + mgr->length += mgr->addressblock; + } + return mgr->memory[mgr->next++] = tcalloc(n, nbytes); +} + +inline void MAllocateMatrixType(MemoryManager* mgr, int type, matrix* m, int rows, int cols) +{ + AllocateMatrixType(type, m, rows, cols); + if (rows || cols) + { + ManageMatrix(mgr, m); + } +} + +void FreeMemory(MemoryManager* mgr) +{ + int i; + for (i = 0; i < mgr->nextm; i++) + { + if (mgr->matrices[i]->type) DeallocateMatrix(mgr->matrices[i]); + } + free(mgr->matrices); + mgr->matrices = 0; + for (i = 0; i < mgr->next; i++) + { + free(mgr->memory[i]); + } + free(mgr->memory); + mgr->memory = 0; +} + +MemoryManager CreateMemoryManager(int InitialLength, int InitialMatrices, int AddressBlockSize, int MatrixAddressBlockSize) +{ + MemoryManager mgr; + mgr.next = 0; + mgr.nextm = 0; + if (InitialLength <= 0) InitialLength = 1; + if (InitialMatrices <= 0) InitialMatrices = 1; + if (AddressBlockSize <= 5) AddressBlockSize = 5; + if (MatrixAddressBlockSize <= 5) MatrixAddressBlockSize = 5; + mgr.length = InitialLength; + mgr.lengthm = InitialMatrices; + mgr.memory = tcalloc(InitialLength, sizeof(void*)); + mgr.matrices = tcalloc(InitialMatrices, sizeof(void*)); + mgr.addressblock = AddressBlockSize; + mgr.addressblockm = MatrixAddressBlockSize; + return mgr; +} + +/*CreateMemoryGrower initializes a memory grower structure.*/ +MemoryGrower CreateMemoryGrower(int pointers, int blocksize) +{ + MemoryGrower g; + if (pointers < 1 || blocksize < 1) + { + merror(0, "CREATEMEMORYGROWER: Parameters are non-positive"); + memset(&g, 0, sizeof(MemoryGrower)); + return g; + } + + g.blocksize = blocksize; + g.memories = pointers; + g.memory = tcalloc(pointers, sizeof(void*)); + g.capacity = tcalloc(pointers, sizeof(int)); + g.next = 0; + return g; +} + +void* growMalloc(MemoryGrower* g, void* memory, int size) +{ + /*If the pointer is null, allocate some new memory.*/ + if (! g) + { + merror(0, "MEMORYGROWER: The pointer to the grower is null"); + return 0; + } + if (! memory) + { + if (g->next == g->memories) + { + merror(0, "MEMORYGROWER: Too many pointers registered with the grower"); + return 0; + } + if (size < g->blocksize) size = g->blocksize; + g->memory[g->next] = tmalloc(size); + g->capacity[g->next] = size; + return g->memory[g->next++]; + } + else + { + /*Otherwise, find the index of the memory record.*/ + int i; + for (i = 0; i < g->next; i++) + { + if (memory == g->memory[i]) break; + } + if (i == g->next) + { + merror(0, "MEMORYGROWER: The memory did not originate with the grower"); + return 0; + } + /*If the request size is smaller than the current capacity return without + reallocating.*/ + if (size < g->capacity[i]) + { + return memory; + } + /*Otherwise, allocate as necessary.*/ + { + if (size < g->capacity[i] + g->blocksize) size = g->capacity[i] + g->blocksize; + void* newMem = tmalloc(size); + memcpy(newMem, memory, g->capacity[i]); + g->capacity[i] = size; + g->memory[i] = newMem; + free(memory); + return newMem; + } + } +} + +void* growCalloc(MemoryGrower* g, void* memory, int elementSize, int elements) +{ + return growMalloc(g, memory, elementSize * elements); +} + + +/*FreeMemoryGrower deallocates all the memories pointed to by a memory +grower.*/ +void FreeMemoryGrower(MemoryGrower* g) +{ + if (! g) return; + int i; + for (i = 0; i < g->next; i++) + { + free(g->memory[i]); + } + free(g->memory); + free(g->capacity); + memset(g, 0, sizeof(MemoryGrower)); +} Added: 2009_version/spnbox09/MemoryManager.h =================================================================== --- 2009_version/spnbox09/MemoryManager.h (rev 0) +++ 2009_version/spnbox09/MemoryManager.h 2011-04-08 22:36:44 UTC (rev 246) @@ -0,0 +1,75 @@ +#ifndef MEMORYMANAGER_H +#define MEMORYMANAGER_H + +#include "../pnheaders/general.h" +#include "../pnheaders/matrix.h" + +/*The MemoryManager structure is used to store information about dynamically +allocated memory so that it can be freed when appropriate. It stores lists +of pointers to ordinary memory blocks and pointers to matrices.*/ +typedef struct MemoryManager +{ + void** memory; + int length; + int next; + int addressblock; + + matrix** matrices; + int lengthm; + int nextm; + int addressblockm; +} MemoryManager; + +/*ManageMatrix adds a matrix to the list of matrices to free later.*/ +inline void ManageMatrix(MemoryManager* mgr, matrix* m); + +/*ManageMemory adds a block of memory to the list of blocks to be freed later.*/ +inline void ManageMemory(MemoryManager* mgr, void* mem); + +/*mmalloc allocates a block of memory and adds it to the lists.*/ +inline void* mmalloc(MemoryManager* mgr, size_t nbytes); + +/*mcalloc allocates a block of memory for an array and adds to the lists.*/ +inline void* mcalloc(MemoryManager* mgr, size_t n, size_t nbytes); + +/*MAllocateMatrixType is exactly like AllocateMatrixType except that it adds +the newly-allocated matrix to the list of matrices to be freed later.*/ +inline void MAllocateMatrixType(MemoryManager* mgr, int type, matrix* m, int rows, int cols); + +/*FreeMemory frees the memory blocks and matrices listed by a memory manager.*/ +void FreeMemory(MemoryManager* mgr); + +/*CreateMemoryManager initializes a memory manager structure. InitialLength +and InitialMatrices are the initial sizes of the lists that hold memory block +and matrix addresses, respectively. Both these parameters must be at least 1 and +will be set to 1 automatically if passed as less than that. +AddressBlockSize and MatrixAddressBlockSize are the number of additional +addresses that memory will be allocated for each time the list of memory block +addresses or matrix addresses respectively become full. These must be at least +five and will be set to five automatically if passed as less than that.*/ +MemoryManager CreateMemoryManager(int InitialLength, int InitialMatrices, int AddressBlockSize, int MatrixAddressBlockSize); + +/*The MemoryGrower structure maintains the information needed to have a region +of memory that can be increased in size several times before a time-consuming +reallocation is necessary.*/ +typedef struct MemoryGrower +{ + void** memory; + int * capacity; + int blocksize, memories, next; +} MemoryGrower; + +/*CreateMemoryGrower initializes a memory grower structure.*/ +MemoryGrower CreateMemoryGrower(int pointers, int blocksize); + +/*growMalloc and growCalloc grow the specified piece of memory to the given +capacity. If the pointer to the memory is null, new memory is allocated. If the +pointer points to a piece of memory the memorygrower is not responsible for the +function fails.*/ +void* growMalloc(MemoryGrower* g, void* memory, int size); +void* growCalloc(MemoryGrower* g, void* memory, int elementSize, int elements); + +/*FreeMemoryGrower deallocates all the memories pointed to by a memory +grower.*/ +void FreeMemoryGrower(MemoryGrower* g); +#endif Added: 2009_version/spnbox09/actn.c =================================================================== --- 2009_version/spnbox09/actn.c (rev 0) +++ 2009_version/spnbox09/actn.c 2011-04-08 22:36:44 UTC (rev 246) @@ -0,0 +1,459 @@ +#include <stdlib.h> +#include "../pnheaders/matrix.h" +#include "matrixmath.h" +#include "extendedmatrix.h" +#include "MemoryManager.h" +#include "spnbox.h" + +static int CheckParams(matrix* Dm, matrix* Dp, int** X, int* XCount, matrix *Dcm, matrix *Dcp, int update); + +static int isUnique(matrix* D, int* X, int XCount); + +static actn_r BuildResult(matrix* Dm, matrix* Dp, int* cullPlace, int* cullTrans); + +static int* cullPlaces(matrix* Dp, int* cullTransition); + +static int* updateURT(matrix* Dm, matrix* Dp, matrix* Dcm, matrix* Dcp); + +static int CheckParams(matrix* Dm, matrix* Dp, int** X, int* XCount, matrix *Dcm, matrix *Dcp, int update); + +actn_r actn(matrix* Dm, matrix* Dp, int* X, int XCount, matrix *Dcm, matrix *Dcp, int update, int checkUnique) +{ + actn_r result; + nltrans_r nltransResult; + MemoryManager memory; + matrix D; /*The incidence matrix*/ + int *cullTransition; /*An array of flags, one for each transition, set if it + should be culled (is unraisable)*/ + int *cullPlace; /*An array of flags, one for each place, set if the place + should be culled.*/ + + /*Initialize the error return value*/ + memset(&result, 0, sizeof(actn_r)); + + /*Initialize the memory manager*/ + memory = CreateMemoryManager(5, 5, 0, 0); + + /*Check the parameters.*/ + if (! CheckParams(Dm, Dp, &X, &XCount, Dcm, Dcp, update)) return result; + + /*Get the incidence matrix - we'll need it later.*/ + D = SubtractMatrix(Dp, Dm, (matrix*) 2); + ManageMatrix(&memory, &D); + + if (update) + { + /*If we are in update mode, use the updateURT function to get the + unraisable transitions.*/ + cullTransition = updateURT(Dm, Dp, Dcm, Dcp); + } + else + { + /*Otherwise, use nltrans to get the list of unraisable transitions.*/ + nltransResult = nltrans(&D, X, XCount); + if (! (nltransResult.dtrCount)) + { + /*If the call failed, fail.*/ + FreeMemory(&memory); + merror(0, "ACTN: nltrans call failed"); + return result; + } + else + { + cullTransition = nltransResult.dtr; + } + } + ManageMemory(&memory, cullTransition); + + /*Build the cullPlace flags, which will be cleared only for places that + have nonzero input arcs from transitions that are not being culled.*/ + cullPlace = cullPlaces(Dp, cullTransition); + ManageMemory(&memory, cullPlace); + + /*Build the final output.*/ + result = BuildResult(Dm, Dp, cullPlace, cullTransition); + + /*Do an isUnique test only if the checkUnique flag is set, since the test + does several linear programming problems and is thus rather slow.*/ + if (checkUnique) + { + result.unique = isUnique(&D, X, XCount); + } + + /*Clean up.*/ + FreeMemory(&memory); + + return result; +} + +/******************************************************************************* +isUnique examines the petri net and the given set of unraisable transitions to +determine if the live subnet that will be returned is unique. It is only called +when the actn caller requests it.*/ +int isUnique(matrix* D, int* X, int XCount) +{ + /*We will be doing a linear programming problem for each raisable transition. + The constraint matrix will be the subset of D having only the columns + corresponding to transitions not in X, with a row of 1s concatenated onto the + bottom, and the column corresponding to whichever transition is currently + being tested removed (or in this case, zeroed).*/ + matrix Dx, dx; + int i, j, Transitions = 0; + int* UnraisableT; + double* B; + short int *IntList; + ipsolve_r result; + + //If no transitions are being evaluated, return true. + if ((Transitions = NumberOfColumns(*D) - XCount) <= 0) return 1; + /*Build a flag array of the columns whose indices are in X.*/ + UnraisableT = tcalloc(NumberOfColumns(*D), sizeof(int)); + for (i = 0; i < XCount; i++) + { + UnraisableT[X[i]] = 1; + } + /*Build Dx. It should include only columns of D whose indices are not in X. + It should be optimized for column ops.*/ + AllocateMatrixType(2, &Dx, Transitions, NumberOfRows(*D) + 1); + TransposeMatrix(&Dx); + j = 0; + for (i = 0; i < NumberOfColumns(*D); i++) + { + if (! UnraisableT[i]) + { + /*Fill in the last row.*/ + SetMatrixEl(&Dx, NumberOfRows(*D), j, 1); + /*Fill in the other rows*/ + CopyBlock(NumberOfRows(*D), 1, D, 0, i, &Dx, 0, j++); + } + } + //We are done with the flag array. Free memory. + free(UnraisableT); + + /*Allocate space to record the values of the current column while it is + zeroed. Make it a type-2 transpose to optimize the column-swap operation.*/ + AllocateMatrixType(1, &dx, 1, NumberOfRows(*D) + 1); + TransposeMatrix(&dx); + + /*Build B. It is all zeroes except for a 1 in the last element.*/ + B = tcalloc(NumberOfRows(*D) + 1, sizeof(double)); + B[NumberOfRows(*D)] = 1; + + /*IntList needs to be all zeroes to override the default of all 1s.*/ + IntList = tcalloc(Transitions, sizeof(short int)); + + /*Iterate through each transition*/ + for (i = 0; i < Transitions; i++) + { + /*If there is a previous transition to restore, restore it.*/ + if (i) SwapColumns(&Dx, &dx, i - 1, 0); + /*Swap out the current transition. Because dx is a column of zeros this + will effectively zero the current transition and save a copy in dx for later + restoration.*/ + SwapColumns(&Dx, &dx, i, 0); + + //ipsolve_r ipsolve(matrix* L, double* B, double* f, short int *IntList, double *ub, double *lb, short int *ctype); + result = ipsolve(&Dx, B, 0, IntList, 0, 0, 0); + if (result.res) free(result.res); + + /*If we get a valid solution, then free memory and return false.*/ + if (! strcmp(result.mhow, HOW_OK)) + { + free(IntList); + free(B); + DeallocateMatrix(&Dx); + DeallocateMatrix(&dx); + return 0; + } + } + //If we get through all transition without returning false, return true. + free(IntList); + free(B); + DeallocateMatrix(&Dx); + DeallocateMatrix(&dx); + return 1; +} + +/******************************************************************************* +BuildResult takes the list of places and transitions to cull from the total net +and builds the active subnet. It returns the result structure that will be +returned by actn. +*/ +actn_r BuildResult(matrix* Dm, matrix* Dp, int* cullPlace, int* cullTrans) +{ + int Places = 0, Transitions = 0, i, j, k, l; + actn_r result; + + /*All matrices are zeroed initially.*/ + memset(&result, 0, sizeof(actn_r)); + + /*Count the number of places and transitions that are going to be left after + culling.*/ + for (i = 0; i < NumberOfRows(*Dm); i++) + { + if (! cullPlace[i]) Places++; + } + for (i = 0; i < NumberOfColumns(*Dm); i++) + { + if (! cullTrans[i]) Transitions++; + } + + /*Allocate space. Dma/Dmp are the same size as the original matrices but + contain only elements in non-culled rows and columns. Dmra/Dpra contain only + non-culled rows and columns. TA holds the indices of kept transitions.*/ + if (Places && Transitions) + { + AllocateMatrixType(2, &result.Dmra, Places, Transitions); + AllocateMatrixType(2, &result.Dpra, Places, Transitions); + } + AllocateMatrixType(2, &result.Dma, NumberOfRows(*Dm), NumberOfColumns(*Dm)); + AllocateMatrixType(2, &result.Dpa, NumberOfRows(*Dm), NumberOfColumns(*Dm)); + result.TA = tcalloc(Transitions, sizeof(int)); + result.TACount = Transitions; + /*Do the copy. k and l indicate the row and column numbers in the Dmra/Dpra + matrices. Fill in TA while we're at it.*/ + l = 0; + for (j = 0; j < NumberOfColumns(*Dm); j++) + { + if (cullTrans[j]) continue; + k = 0; + for (i = 0; i < NumberOfRows(*Dm); i++) + { + if (cullPlace[i]) continue; + SetMatrixEl(&result.Dma, i, j, GetMatrixEl(Dm, i, j)); + SetMatrixEl(&result.Dpa, i, j, GetMatrixEl(Dp, i, j)); + SetMatrixEl(&result.Dmra, k, l, GetMatrixEl(Dm, i, j)); + SetMatrixEl(&result.Dpra, k, l, GetMatrixEl(Dp, i, j)); + k++; + } + result.TA[l] = j; + l++; + } + return result; +} +/******************************************************************************* +cullPlaces examines the Petri net and the list of transitions to cull and +returns an array of integer flags, one for each place, indicating whether that +place should be culled. +*/ +int* cullPlaces(matrix* Dp, int* cullTransition) +{ + int i, j; + int *cull; + /*Allocate and initialize the return value cull. It will be clear only for + places that have nonzero output arcs to transitions that are not being + culled.*/ + cull = tcalloc(NumberOfRows(*Dp), sizeof(int)); + for (i = 0; i < NumberOfRows(*Dp); i++) + { + /*Look to see if the current place has any nonzero output arcs to + transitions not being culled.*/ + for (j = 0; j < NumberOfColumns(*Dp); j++) + { + if (GetMatrixEl(Dp, i, j) && (! cullTransition[j])) + { + break; + } + } + /*If there were no nonzero output arcs set the place flag.*/ + if (j == NumberOfColumns(*Dp)) + { + cull[i] = 1; + } + } + return cull; +} + +/******************************************************************************* +updateURT examines the Petri net and the predefined active subnet if given and +returns an array of transitions that are unraisable given the active subnet. +This is used to determine transitions to cull if in update mode. +*/ +int* updateURT(matrix* Dm, matrix* Dp, matrix* Dcm, matrix* Dcp) +{ + /*This function builds a list of unraisable transitions in Dm/Dp by examining + Dcm/Dcp.*/ + int Places, Transitions, SubPlaces, SubTransitions, i, j, keepGoing; + /*These are each flag arrays set to indicate live places or transitions at + various times throughout the algorithm.*/ + int *URT, *Trans = 0, *Place = 0; + + Places = NumberOfRows(*Dm); + Transitions = NumberOfColumns(*Dm); + SubPlaces = NumberOfRows(*Dcm); + SubTransitions = NumberOfColumns(*Dcm); + + /*URT is the return value. It has a flag for each transition.*/ + URT = tcalloc(Transitions, sizeof(int)); + /*Trans and Place both have flags only for each of the possible new + transitions or places that can be added.*/ + if (Places - SubPlaces) + { + Place = tcalloc(Places - SubPlaces, sizeof(int)); + } + if (Transitions - SubTransitions) + { + Trans = tcalloc(Transitions - SubTransitions, sizeof(int)); + } + + /*URT is a flag vector with an element for each transition. It is initially + cleared only for non-null columns of Dcm/Dcp, where column numbers in Dcm/Dcp + map to the same column numbers in Dm/Dp.*/ + for (i = 0; i < SubTransitions; i++) + { + /*See if the current column of Dcm/Dcp is non-null.*/ + for (j = 0; j < SubPlaces; j++) + { + if (GetMatrixEl(Dcm, j, i) || GetMatrixEl(Dcp, j, i)) + { + break; + } + } + /*If it was null, set the URT flag.*/ + if (j == SubPlaces) + { + URT[i] = 1; + } + } + /*Fill the additional elements of URT, the ones not taken care of above.*/ + for (i = SubTransitions; i < Transitions; i++) + { + URT[i] = 1; + } + + /*Now, we loop. For the first iteration we have to do something special. Use + keepGoing = -1 to indicate first loop iteration.*/ + keepGoing = -1; + do + { + /*The place flag should be set for any place (in Dm/Dp beyond those mapped + to by Dcm/Dcp) such that the place has at least one nonzero output arc to + a transition that is flagged in the current transition list. It should + be cleared for every other place. On the first loop iteration, rather + than using the current transition list (which maps to the columns in the + right of Dm/Dp that have no corresponding columns in Dcm/Dcp), we use logic + inverse of URT, which maps to all columns in Dm/Dp. The keepGoing flag will + be set to -1 on the first iteration.*/ + memset(Place, 0, sizeof(int) * (Places - SubPlaces)); + if (keepGoing > 0) + { + for (i = SubPlaces; i < Places; i++) + { + /*Check to see if the current place has at least one nonzero output arc + to a transition flagged in the current transition list.*/ + for (j = SubTransitions; j < Transitions; j++) + { + if (Trans[j - SubTransitions] && GetMatrixEl(Dm, i, j)) + { + /*If it does, set the flag and break out of the test loop.*/ + Place[i - SubPlaces] = 1; + break; + } + } + } + } + else + { + for (i = SubPlaces; i < Places; i++) + { + /*Check to see if the current place has at least one nonzero output arc + to a transition not flagged in URT.*/ + for (j = 0; j < SubTransitions; j++) + { + if ((! URT[j]) && GetMatrixEl(Dm, i, j)) + { + /*If it does, set the flag and break out of the test loop.*/ + Place[i - SubPlaces] = 1; + break; + } + } + } + } + /*Similarly, the transition flag should be set for any transition in Dm/Dp + beyond those mapped to by Dcm/Dcp such that the transition has at least one + nonzero input arc to a place that is flagged in the current place list. + Additionally, we clear every flag of URT that corresponds to a + transition whose flag is set in Trans. Finally, the overall loop will + continue only until Trans is entirely empty. Set the keepGoing flag + if any element of Trans is set.*/ + keepGoing = 0; + memset(Trans, 0, sizeof(int) * (Transitions - SubTransitions)); + for (j = SubTransitions; j < Transitions; j++) + { + for (i = SubPlaces; i < Places; i++) + { + if (Place[i - SubPlaces] && GetMatrixEl(Dp, i, j)) + { + Trans[j - SubTransitions] = 1; + /*Clear the appropriate URT flag.*/ + URT[j] = 0; + /*Set the keepGoing flag.*/ + keepGoing = 1; + break; + } + } + } + } while (keepGoing); + /*Free memory*/ + if (Place) free(Place); + if (Trans) free(Trans); + /*Return*/ + return URT; +} + +/******************************************************************************* +CheckParams checks the parameters to make sure required parameters are present, +checks some basic validity, and makes sure that all array pointers are null if +their counts are zero and vice-versa.*/ +int CheckParams(matrix* Dm, matrix* Dp, int** X, int* XCount, matrix *Dcm, matrix *Dcp, int update) +{ + int Rows0, Cols0, Rows1, Cols1; + /*Dm and Dp are required and must be the same size.*/ + if (! (Dm && Dp)) + { + merror(0, "ACTN: Dm or Dp was not given"); + return 0; + } + Rows0 = NumberOfRows(*Dm); + Cols0 = NumberOfColumns(*Dm); + if (Rows0 != NumberOfRows(*Dp) || Cols0 != NumberOfColumns(*Dp)) + { + merror(0, "ACTN: The dimensions of Dm and Dp do not match"); + return 0; + } + + /*X is not required. Make sure that XCount is zero if X is null and vice- + versa.*/ + if (! *X) + { + *XCount = 0; + } + else if (! *XCount) + { + *X = 0; + } + + /*If update is nonzero, Dcm and Dcp are required. They cannot be larger than + Dm/Dp in either dimension and they must be the same size.*/ + if (update) + { + if (! (Dcm && Dcp)) + { + merror(0, "ACTN: Dcm or Dcp was not given while update was nonzero"); + return 0; + } + Rows1 = NumberOfRows(*Dcm); + Cols1 = NumberOfColumns(*Dcm); + if (NumberOfRows(*Dcp) != Rows1 || NumberOfColumns(*Dcp) != Cols1) + { + merror(0, "ACTN: Dcm and Dcp are not the same size"); + return 0; + } + if (Rows1 > Rows0 || Cols1 > Cols0) + { + merror(0, "ACTN: Dcm and Dcp are larger than Dm and Dp"); + return 0; + } + } + return 1; +} Added: 2009_version/spnbox09/admcon.c =================================================================== --- 2009_version/spnbox09/admcon.c (rev 0) +++ 2009_version/spnbox09/admcon.c 2011-04-08 22:36:44 UTC (rev 246) @@ -0,0 +1,613 @@ +#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, 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.*/ + 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 + 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 + 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))) + { + result.how = 0; + 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.*/ + 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 (dp - dm < 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(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 + 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, matrix *Z) +{ + /*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) + 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, p->TucCount + p->TuoCount + p->TuoCount + p->ntCount + 1, NumberOfRows(*Z)); + + int i, j, k; + for (i = 0; i < NumberOfColumns(DX); i++) + { + /*Fill in Auc.*/ + for (j = 0; j < p->TucCount; j++) + { + 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, 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, j + p->TucCount + (2 * p->TuoCount), i, k); + } + } + /*Fill in d.*/ + for (i = 0; i < p->apCount; i++) + { + SetMatrixEl(&DX, NumberOfRows(DX) - 1, p->apl[i], 1); + } + /*Deallocate Z. It will not be needed anymore.*/ + DeallocateMatrix(Z); + + /*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) + { + for (i = 0; i < NumberOfRows(DX); i++) + { + 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); + } + } + 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, k, i)); + } + } + + 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 + 1; +} + +/******************************************************************************* +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; +} Added: 2009_version/spnbox09/asiph.c =================================================================== --- 2009_version/spnbox09/asiph.c (rev 0) +++ 2009_version/spnbox09/asiph.c 2011-04-08 22:36:44 UTC (rev 246) @@ -0,0 +1,901 @@ +#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); + FreeMemory(&mem); + 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 algo... [truncated message content] |