From 39df2438491f7d4f81315f3f72578e5fd08dcb46 Mon Sep 17 00:00:00 2001 From: Leonardo Brenner <leonardo.brenner@univ-amu.fr> Date: Wed, 4 Oct 2023 18:36:59 +0200 Subject: [PATCH] First commit --- Makefile | 261 ++ bin/.DS_Store | Bin 0 -> 8196 bytes bin/Release/simuleau | Bin 0 -> 305464 bytes examples/batch1.bpn | 47 + examples/batch11.bpn | 44 + examples/batch111.bpn | 47 + examples/batch2.bpn | 47 + examples/batch21.bpn | 47 + examples/batch22.bpn | 48 + examples/batch23.bpn | 47 + examples/batch24.bpn | 47 + examples/batch25.bpn | 47 + examples/batch26.bpn | 47 + examples/batch27.bpn | 47 + examples/bp.bpn | 27 + examples/bpn1.bpn | 17 + examples/bpn2.bpn | 21 + examples/bpn3.bpn | 26 + examples/bpn4.bpn | 39 + examples/bpn5.bpn | 53 + examples/bpn6.bpn | 21 + examples/control.bpn | 51 + examples/cpn2p.bpn | 30 + examples/cpn5p.bpn | 47 + examples/ct.bpn | 27 + examples/discretetransition.bpn | 27 + examples/discretetransition.in | 12 + examples/dpn_1p.bpn | 24 + examples/dpn_3p.bpn | 35 + examples/dpn_4p.bpn | 37 + examples/fig12.bpn | 82 + examples/gbpn1.bpn | 77 + examples/hpn3p.bpn | 33 + examples/hpn5p.bpn | 40 + examples/lego.bpn | 70 + examples/optimal.bpn | 53 + examples/periodic1.bpn | 51 + examples/petrinets.bpn | 52 + examples/pn_discrets.bpn | 27 + examples/pureCPN.bpn | 47 + examples/pureCPN2.bpn | 47 + examples/pureCPN21.bpn | 52 + examples/pureCPN3.bpn | 45 + examples/pureCPN31.bpn | 41 + examples/pureCPN4.bpn | 45 + examples/pureCPN5.bpn | 45 + examples/pureCPN6.bpn | 45 + examples/pureCPN7.bpn | 45 + examples/tbpn.bpn | 22 + examples/tbpn2.bpn | 41 + examples/tbpn3.bpn | 35 + examples/tbpn4.bpn | 25 + examples/test.bpn | 67 + examples/test1.bpn | 32 + examples/test2.bpn | 38 + examples/test_steady.bpn | 76 + simuleau.cbp | 130 + simuleau.layout | 230 ++ src/.DS_Store | Bin 0 -> 6148 bytes src/bpn/arc.cpp | 22 + src/bpn/arc.h | 29 + src/bpn/batch.cpp | 260 ++ src/bpn/batch.h | 131 + src/bpn/batchplace.cpp | 1622 ++++++++++++ src/bpn/batchtransition.cpp | 269 ++ src/bpn/bpn.cpp | 4117 ++++++++++++++++++++++++++++++ src/bpn/bpn.h | 144 ++ src/bpn/continuousplace.cpp | 825 ++++++ src/bpn/continuoustransition.cpp | 315 +++ src/bpn/controllablebatch.cpp | 404 +++ src/bpn/discreteplace.cpp | 233 ++ src/bpn/discretetransition.cpp | 225 ++ src/bpn/firingquantity.cpp | 98 + src/bpn/firingquantity.h | 45 + src/bpn/flow.cpp | 136 + src/bpn/flow.h | 52 + src/bpn/node.cpp | 274 ++ src/bpn/node.h | 61 + src/bpn/place.cpp | 146 ++ src/bpn/place.h | 367 +++ src/bpn/transition.cpp | 358 +++ src/bpn/transition.h | 189 ++ src/bpn/triangularbatchplace.cpp | 1114 ++++++++ src/interf/bpnfile.h | 5 + src/interf/error_msgs.h | 92 + src/interf/glc.y | 773 ++++++ src/interf/interf.cpp | 690 +++++ src/interf/interf.h | 152 ++ src/interf/lex.yy.c | 2152 ++++++++++++++++ src/interf/lex.yy.cpp | 2153 ++++++++++++++++ src/interf/prf.cpp | 209 ++ src/interf/prf.h | 69 + src/interf/test | 54 + src/interf/timer.cpp | 103 + src/interf/timer.h | 56 + src/interf/tokens.l | 104 + src/interf/y.output | 2550 ++++++++++++++++++ src/interf/y.tab.cpp | 2642 +++++++++++++++++++ src/interf/y.tab.h | 152 ++ src/interf/y.tab.hpp | 156 ++ src/simul/breakpoint.cpp | 170 ++ src/simul/breakpoint.h | 54 + src/simul/event.cpp | 222 ++ src/simul/event.h | 89 + src/simul/schedule.cpp | 967 +++++++ src/simul/schedule.h | 85 + src/simul/simtime.cpp | 99 + src/simul/simtime.h | 41 + src/simul/simulate.cpp | 352 +++ src/simul/simulate.h | 65 + src/simuleau.cpp | 180 ++ src/simuleau.h | 259 ++ 112 files changed, 28994 insertions(+) create mode 100644 Makefile create mode 100644 bin/.DS_Store create mode 100755 bin/Release/simuleau create mode 100644 examples/batch1.bpn create mode 100644 examples/batch11.bpn create mode 100644 examples/batch111.bpn create mode 100644 examples/batch2.bpn create mode 100644 examples/batch21.bpn create mode 100644 examples/batch22.bpn create mode 100644 examples/batch23.bpn create mode 100644 examples/batch24.bpn create mode 100644 examples/batch25.bpn create mode 100644 examples/batch26.bpn create mode 100644 examples/batch27.bpn create mode 100644 examples/bp.bpn create mode 100644 examples/bpn1.bpn create mode 100644 examples/bpn2.bpn create mode 100644 examples/bpn3.bpn create mode 100644 examples/bpn4.bpn create mode 100644 examples/bpn5.bpn create mode 100644 examples/bpn6.bpn create mode 100644 examples/control.bpn create mode 100644 examples/cpn2p.bpn create mode 100644 examples/cpn5p.bpn create mode 100644 examples/ct.bpn create mode 100644 examples/discretetransition.bpn create mode 100644 examples/discretetransition.in create mode 100644 examples/dpn_1p.bpn create mode 100644 examples/dpn_3p.bpn create mode 100644 examples/dpn_4p.bpn create mode 100644 examples/fig12.bpn create mode 100644 examples/gbpn1.bpn create mode 100644 examples/hpn3p.bpn create mode 100644 examples/hpn5p.bpn create mode 100644 examples/lego.bpn create mode 100644 examples/optimal.bpn create mode 100644 examples/periodic1.bpn create mode 100644 examples/petrinets.bpn create mode 100644 examples/pn_discrets.bpn create mode 100644 examples/pureCPN.bpn create mode 100644 examples/pureCPN2.bpn create mode 100644 examples/pureCPN21.bpn create mode 100644 examples/pureCPN3.bpn create mode 100644 examples/pureCPN31.bpn create mode 100644 examples/pureCPN4.bpn create mode 100644 examples/pureCPN5.bpn create mode 100644 examples/pureCPN6.bpn create mode 100644 examples/pureCPN7.bpn create mode 100644 examples/tbpn.bpn create mode 100644 examples/tbpn2.bpn create mode 100644 examples/tbpn3.bpn create mode 100644 examples/tbpn4.bpn create mode 100644 examples/test.bpn create mode 100644 examples/test1.bpn create mode 100644 examples/test2.bpn create mode 100644 examples/test_steady.bpn create mode 100644 simuleau.cbp create mode 100644 simuleau.layout create mode 100644 src/.DS_Store create mode 100644 src/bpn/arc.cpp create mode 100644 src/bpn/arc.h create mode 100644 src/bpn/batch.cpp create mode 100644 src/bpn/batch.h create mode 100644 src/bpn/batchplace.cpp create mode 100644 src/bpn/batchtransition.cpp create mode 100644 src/bpn/bpn.cpp create mode 100644 src/bpn/bpn.h create mode 100644 src/bpn/continuousplace.cpp create mode 100644 src/bpn/continuoustransition.cpp create mode 100644 src/bpn/controllablebatch.cpp create mode 100644 src/bpn/discreteplace.cpp create mode 100644 src/bpn/discretetransition.cpp create mode 100644 src/bpn/firingquantity.cpp create mode 100644 src/bpn/firingquantity.h create mode 100644 src/bpn/flow.cpp create mode 100644 src/bpn/flow.h create mode 100644 src/bpn/node.cpp create mode 100644 src/bpn/node.h create mode 100644 src/bpn/place.cpp create mode 100644 src/bpn/place.h create mode 100644 src/bpn/transition.cpp create mode 100644 src/bpn/transition.h create mode 100644 src/bpn/triangularbatchplace.cpp create mode 100644 src/interf/bpnfile.h create mode 100644 src/interf/error_msgs.h create mode 100644 src/interf/glc.y create mode 100644 src/interf/interf.cpp create mode 100644 src/interf/interf.h create mode 100644 src/interf/lex.yy.c create mode 100644 src/interf/lex.yy.cpp create mode 100644 src/interf/prf.cpp create mode 100644 src/interf/prf.h create mode 100644 src/interf/test create mode 100644 src/interf/timer.cpp create mode 100644 src/interf/timer.h create mode 100644 src/interf/tokens.l create mode 100644 src/interf/y.output create mode 100644 src/interf/y.tab.cpp create mode 100644 src/interf/y.tab.h create mode 100644 src/interf/y.tab.hpp create mode 100644 src/simul/breakpoint.cpp create mode 100644 src/simul/breakpoint.h create mode 100644 src/simul/event.cpp create mode 100644 src/simul/event.h create mode 100644 src/simul/schedule.cpp create mode 100644 src/simul/schedule.h create mode 100644 src/simul/simtime.cpp create mode 100644 src/simul/simtime.h create mode 100644 src/simul/simulate.cpp create mode 100644 src/simul/simulate.h create mode 100644 src/simuleau.cpp create mode 100644 src/simuleau.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4668d7c --- /dev/null +++ b/Makefile @@ -0,0 +1,261 @@ +#------------------------------------------------------------------------------# +# This makefile was generated by 'cbp2make' tool rev.147 # +#------------------------------------------------------------------------------# + + +WORKDIR = `pwd` + +CC = gcc +CXX = g++ +AR = ar +LD = g++ +WINDRES = windres + +INC = -Isrc +CFLAGS = -Wall -std=c++11 -fexceptions -fpermissive +RESINC = +LIBDIR = +LIB = -lglpk -ldl +LDFLAGS = + +INC_DEBUG = $(INC) -Isrc -Isrc/bpn -Isrc/interf -Isrc/simul +CFLAGS_DEBUG = $(CFLAGS) -w -pg -g -Wunused-result -O0 -D_SIMULEAU_DEBUG_ +RESINC_DEBUG = $(RESINC) +RCFLAGS_DEBUG = $(RCFLAGS) +LIBDIR_DEBUG = $(LIBDIR) -L/usr/local/lib -L/usr/local/include -L/usr/include -L/usr/lib/x86_64-linux-gnu/ +LIB_DEBUG = $(LIB) +LDFLAGS_DEBUG = $(LDFLAGS) -pg -static-libstdc++ -static-libgcc +OBJDIR_DEBUG = obj/Debug +DEP_DEBUG = +OUT_DEBUG = bin/Debug/simuleau + +INC_RELEASE = $(INC) -Isrc/bpn -Isrc/simul -Isrc -Isrc/interf +CFLAGS_RELEASE = $(CFLAGS) -O2 +RESINC_RELEASE = $(RESINC) +RCFLAGS_RELEASE = $(RCFLAGS) +LIBDIR_RELEASE = $(LIBDIR) +LIB_RELEASE = $(LIB) +LDFLAGS_RELEASE = $(LDFLAGS) -s +OBJDIR_RELEASE = obj/Release +DEP_RELEASE = +OUT_RELEASE = bin/Release/simuleau + +OBJ_DEBUG = $(OBJDIR_DEBUG)/src/simul/breakpoint.o $(OBJDIR_DEBUG)/src/interf/interf.o $(OBJDIR_DEBUG)/src/interf/lex.yy.o $(OBJDIR_DEBUG)/src/interf/prf.o $(OBJDIR_DEBUG)/src/interf/timer.o $(OBJDIR_DEBUG)/src/interf/y.tab.o $(OBJDIR_DEBUG)/src/simul/event.o $(OBJDIR_DEBUG)/src/simul/schedule.o $(OBJDIR_DEBUG)/src/simul/simtime.o $(OBJDIR_DEBUG)/src/simul/simulate.o $(OBJDIR_DEBUG)/src/simuleau.o $(OBJDIR_DEBUG)/src/bpn/discretetransition.o $(OBJDIR_DEBUG)/src/bpn/batch.o $(OBJDIR_DEBUG)/src/bpn/batchplace.o $(OBJDIR_DEBUG)/src/bpn/batchtransition.o $(OBJDIR_DEBUG)/src/bpn/bpn.o $(OBJDIR_DEBUG)/src/bpn/continuousplace.o $(OBJDIR_DEBUG)/src/bpn/continuoustransition.o $(OBJDIR_DEBUG)/src/bpn/controllablebatch.o $(OBJDIR_DEBUG)/src/bpn/discreteplace.o $(OBJDIR_DEBUG)/src/bpn/arc.o $(OBJDIR_DEBUG)/src/bpn/firingquantity.o $(OBJDIR_DEBUG)/src/bpn/flow.o $(OBJDIR_DEBUG)/src/bpn/node.o $(OBJDIR_DEBUG)/src/bpn/place.o $(OBJDIR_DEBUG)/src/bpn/transition.o $(OBJDIR_DEBUG)/src/bpn/triangularbatchplace.o + +OBJ_RELEASE = $(OBJDIR_RELEASE)/src/simul/breakpoint.o $(OBJDIR_RELEASE)/src/interf/interf.o $(OBJDIR_RELEASE)/src/interf/lex.yy.o $(OBJDIR_RELEASE)/src/interf/prf.o $(OBJDIR_RELEASE)/src/interf/timer.o $(OBJDIR_RELEASE)/src/interf/y.tab.o $(OBJDIR_RELEASE)/src/simul/event.o $(OBJDIR_RELEASE)/src/simul/schedule.o $(OBJDIR_RELEASE)/src/simul/simtime.o $(OBJDIR_RELEASE)/src/simul/simulate.o $(OBJDIR_RELEASE)/src/simuleau.o $(OBJDIR_RELEASE)/src/bpn/discretetransition.o $(OBJDIR_RELEASE)/src/bpn/batch.o $(OBJDIR_RELEASE)/src/bpn/batchplace.o $(OBJDIR_RELEASE)/src/bpn/batchtransition.o $(OBJDIR_RELEASE)/src/bpn/bpn.o $(OBJDIR_RELEASE)/src/bpn/continuousplace.o $(OBJDIR_RELEASE)/src/bpn/continuoustransition.o $(OBJDIR_RELEASE)/src/bpn/controllablebatch.o $(OBJDIR_RELEASE)/src/bpn/discreteplace.o $(OBJDIR_RELEASE)/src/bpn/arc.o $(OBJDIR_RELEASE)/src/bpn/firingquantity.o $(OBJDIR_RELEASE)/src/bpn/flow.o $(OBJDIR_RELEASE)/src/bpn/node.o $(OBJDIR_RELEASE)/src/bpn/place.o $(OBJDIR_RELEASE)/src/bpn/transition.o $(OBJDIR_RELEASE)/src/bpn/triangularbatchplace.o + +all: debug release + +clean: clean_debug clean_release + +before_debug: + lex -o src/interf/y.tab.cpp src/interf/tokens.l + yacc -tdv -o src/interf/y.tab.cpp src/interf/glc.y + test -d bin/Debug || mkdir -p bin/Debug + test -d $(OBJDIR_DEBUG)/src/simul || mkdir -p $(OBJDIR_DEBUG)/src/simul + test -d $(OBJDIR_DEBUG)/src/interf || mkdir -p $(OBJDIR_DEBUG)/src/interf + test -d $(OBJDIR_DEBUG)/src || mkdir -p $(OBJDIR_DEBUG)/src + test -d $(OBJDIR_DEBUG)/src/bpn || mkdir -p $(OBJDIR_DEBUG)/src/bpn + +after_debug: + +debug: before_debug out_debug after_debug + +out_debug: before_debug $(OBJ_DEBUG) $(DEP_DEBUG) + $(LD) $(LIBDIR_DEBUG) -o $(OUT_DEBUG) $(OBJ_DEBUG) $(LDFLAGS_DEBUG) $(LIB_DEBUG) + +$(OBJDIR_DEBUG)/src/simul/breakpoint.o: src/simul/breakpoint.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/simul/breakpoint.cpp -o $(OBJDIR_DEBUG)/src/simul/breakpoint.o + +$(OBJDIR_DEBUG)/src/interf/interf.o: src/interf/interf.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/interf/interf.cpp -o $(OBJDIR_DEBUG)/src/interf/interf.o + +$(OBJDIR_DEBUG)/src/interf/lex.yy.o: src/interf/lex.yy.cpp + $(CC) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/interf/lex.yy.cpp -o $(OBJDIR_DEBUG)/src/interf/lex.yy.o + +$(OBJDIR_DEBUG)/src/interf/prf.o: src/interf/prf.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/interf/prf.cpp -o $(OBJDIR_DEBUG)/src/interf/prf.o + +$(OBJDIR_DEBUG)/src/interf/timer.o: src/interf/timer.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/interf/timer.cpp -o $(OBJDIR_DEBUG)/src/interf/timer.o + +$(OBJDIR_DEBUG)/src/interf/y.tab.o: src/interf/y.tab.cpp + $(CC) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/interf/y.tab.cpp -o $(OBJDIR_DEBUG)/src/interf/y.tab.o + +$(OBJDIR_DEBUG)/src/simul/event.o: src/simul/event.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/simul/event.cpp -o $(OBJDIR_DEBUG)/src/simul/event.o + +$(OBJDIR_DEBUG)/src/simul/schedule.o: src/simul/schedule.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/simul/schedule.cpp -o $(OBJDIR_DEBUG)/src/simul/schedule.o + +$(OBJDIR_DEBUG)/src/simul/simtime.o: src/simul/simtime.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/simul/simtime.cpp -o $(OBJDIR_DEBUG)/src/simul/simtime.o + +$(OBJDIR_DEBUG)/src/simul/simulate.o: src/simul/simulate.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/simul/simulate.cpp -o $(OBJDIR_DEBUG)/src/simul/simulate.o + +$(OBJDIR_DEBUG)/src/simuleau.o: src/simuleau.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/simuleau.cpp -o $(OBJDIR_DEBUG)/src/simuleau.o + +$(OBJDIR_DEBUG)/src/bpn/discretetransition.o: src/bpn/discretetransition.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/discretetransition.cpp -o $(OBJDIR_DEBUG)/src/bpn/discretetransition.o + +$(OBJDIR_DEBUG)/src/bpn/batch.o: src/bpn/batch.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/batch.cpp -o $(OBJDIR_DEBUG)/src/bpn/batch.o + +$(OBJDIR_DEBUG)/src/bpn/batchplace.o: src/bpn/batchplace.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/batchplace.cpp -o $(OBJDIR_DEBUG)/src/bpn/batchplace.o + +$(OBJDIR_DEBUG)/src/bpn/batchtransition.o: src/bpn/batchtransition.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/batchtransition.cpp -o $(OBJDIR_DEBUG)/src/bpn/batchtransition.o + +$(OBJDIR_DEBUG)/src/bpn/bpn.o: src/bpn/bpn.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/bpn.cpp -o $(OBJDIR_DEBUG)/src/bpn/bpn.o + +$(OBJDIR_DEBUG)/src/bpn/continuousplace.o: src/bpn/continuousplace.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/continuousplace.cpp -o $(OBJDIR_DEBUG)/src/bpn/continuousplace.o + +$(OBJDIR_DEBUG)/src/bpn/continuoustransition.o: src/bpn/continuoustransition.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/continuoustransition.cpp -o $(OBJDIR_DEBUG)/src/bpn/continuoustransition.o + +$(OBJDIR_DEBUG)/src/bpn/controllablebatch.o: src/bpn/controllablebatch.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/controllablebatch.cpp -o $(OBJDIR_DEBUG)/src/bpn/controllablebatch.o + +$(OBJDIR_DEBUG)/src/bpn/discreteplace.o: src/bpn/discreteplace.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/discreteplace.cpp -o $(OBJDIR_DEBUG)/src/bpn/discreteplace.o + +$(OBJDIR_DEBUG)/src/bpn/arc.o: src/bpn/arc.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/arc.cpp -o $(OBJDIR_DEBUG)/src/bpn/arc.o + +$(OBJDIR_DEBUG)/src/bpn/firingquantity.o: src/bpn/firingquantity.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/firingquantity.cpp -o $(OBJDIR_DEBUG)/src/bpn/firingquantity.o + +$(OBJDIR_DEBUG)/src/bpn/flow.o: src/bpn/flow.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/flow.cpp -o $(OBJDIR_DEBUG)/src/bpn/flow.o + +$(OBJDIR_DEBUG)/src/bpn/node.o: src/bpn/node.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/node.cpp -o $(OBJDIR_DEBUG)/src/bpn/node.o + +$(OBJDIR_DEBUG)/src/bpn/place.o: src/bpn/place.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/place.cpp -o $(OBJDIR_DEBUG)/src/bpn/place.o + +$(OBJDIR_DEBUG)/src/bpn/transition.o: src/bpn/transition.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/transition.cpp -o $(OBJDIR_DEBUG)/src/bpn/transition.o + +$(OBJDIR_DEBUG)/src/bpn/triangularbatchplace.o: src/bpn/triangularbatchplace.cpp + $(CXX) $(CFLAGS_DEBUG) $(INC_DEBUG) -c src/bpn/triangularbatchplace.cpp -o $(OBJDIR_DEBUG)/src/bpn/triangularbatchplace.o + +clean_debug: + rm -f $(OBJ_DEBUG) $(OUT_DEBUG) + rm -rf bin/Debug + rm -rf $(OBJDIR_DEBUG)/src/simul + rm -rf $(OBJDIR_DEBUG)/src/interf + rm -rf $(OBJDIR_DEBUG)/src + rm -rf $(OBJDIR_DEBUG)/src/bpn + +before_release: + yacc -tdv -o src/interf/y.tab.cpp src/interf/glc.y + test -d bin/Release || mkdir -p bin/Release + test -d $(OBJDIR_RELEASE)/src/simul || mkdir -p $(OBJDIR_RELEASE)/src/simul + test -d $(OBJDIR_RELEASE)/src/interf || mkdir -p $(OBJDIR_RELEASE)/src/interf + test -d $(OBJDIR_RELEASE)/src || mkdir -p $(OBJDIR_RELEASE)/src + test -d $(OBJDIR_RELEASE)/src/bpn || mkdir -p $(OBJDIR_RELEASE)/src/bpn + +after_release: + +release: before_release out_release after_release + +out_release: before_release $(OBJ_RELEASE) $(DEP_RELEASE) + $(LD) $(LIBDIR_RELEASE) -o $(OUT_RELEASE) $(OBJ_RELEASE) $(LDFLAGS_RELEASE) $(LIB_RELEASE) + +$(OBJDIR_RELEASE)/src/simul/breakpoint.o: src/simul/breakpoint.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/simul/breakpoint.cpp -o $(OBJDIR_RELEASE)/src/simul/breakpoint.o + +$(OBJDIR_RELEASE)/src/interf/interf.o: src/interf/interf.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/interf/interf.cpp -o $(OBJDIR_RELEASE)/src/interf/interf.o + +$(OBJDIR_RELEASE)/src/interf/lex.yy.o: src/interf/lex.yy.cpp + $(CC) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/interf/lex.yy.cpp -o $(OBJDIR_RELEASE)/src/interf/lex.yy.o + +$(OBJDIR_RELEASE)/src/interf/prf.o: src/interf/prf.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/interf/prf.cpp -o $(OBJDIR_RELEASE)/src/interf/prf.o + +$(OBJDIR_RELEASE)/src/interf/timer.o: src/interf/timer.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/interf/timer.cpp -o $(OBJDIR_RELEASE)/src/interf/timer.o + +$(OBJDIR_RELEASE)/src/interf/y.tab.o: src/interf/y.tab.cpp + $(CC) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/interf/y.tab.cpp -o $(OBJDIR_RELEASE)/src/interf/y.tab.o + +$(OBJDIR_RELEASE)/src/simul/event.o: src/simul/event.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/simul/event.cpp -o $(OBJDIR_RELEASE)/src/simul/event.o + +$(OBJDIR_RELEASE)/src/simul/schedule.o: src/simul/schedule.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/simul/schedule.cpp -o $(OBJDIR_RELEASE)/src/simul/schedule.o + +$(OBJDIR_RELEASE)/src/simul/simtime.o: src/simul/simtime.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/simul/simtime.cpp -o $(OBJDIR_RELEASE)/src/simul/simtime.o + +$(OBJDIR_RELEASE)/src/simul/simulate.o: src/simul/simulate.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/simul/simulate.cpp -o $(OBJDIR_RELEASE)/src/simul/simulate.o + +$(OBJDIR_RELEASE)/src/simuleau.o: src/simuleau.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/simuleau.cpp -o $(OBJDIR_RELEASE)/src/simuleau.o + +$(OBJDIR_RELEASE)/src/bpn/discretetransition.o: src/bpn/discretetransition.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/discretetransition.cpp -o $(OBJDIR_RELEASE)/src/bpn/discretetransition.o + +$(OBJDIR_RELEASE)/src/bpn/batch.o: src/bpn/batch.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/batch.cpp -o $(OBJDIR_RELEASE)/src/bpn/batch.o + +$(OBJDIR_RELEASE)/src/bpn/batchplace.o: src/bpn/batchplace.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/batchplace.cpp -o $(OBJDIR_RELEASE)/src/bpn/batchplace.o + +$(OBJDIR_RELEASE)/src/bpn/batchtransition.o: src/bpn/batchtransition.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/batchtransition.cpp -o $(OBJDIR_RELEASE)/src/bpn/batchtransition.o + +$(OBJDIR_RELEASE)/src/bpn/bpn.o: src/bpn/bpn.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/bpn.cpp -o $(OBJDIR_RELEASE)/src/bpn/bpn.o + +$(OBJDIR_RELEASE)/src/bpn/continuousplace.o: src/bpn/continuousplace.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/continuousplace.cpp -o $(OBJDIR_RELEASE)/src/bpn/continuousplace.o + +$(OBJDIR_RELEASE)/src/bpn/continuoustransition.o: src/bpn/continuoustransition.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/continuoustransition.cpp -o $(OBJDIR_RELEASE)/src/bpn/continuoustransition.o + +$(OBJDIR_RELEASE)/src/bpn/controllablebatch.o: src/bpn/controllablebatch.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/controllablebatch.cpp -o $(OBJDIR_RELEASE)/src/bpn/controllablebatch.o + +$(OBJDIR_RELEASE)/src/bpn/discreteplace.o: src/bpn/discreteplace.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/discreteplace.cpp -o $(OBJDIR_RELEASE)/src/bpn/discreteplace.o + +$(OBJDIR_RELEASE)/src/bpn/arc.o: src/bpn/arc.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/arc.cpp -o $(OBJDIR_RELEASE)/src/bpn/arc.o + +$(OBJDIR_RELEASE)/src/bpn/firingquantity.o: src/bpn/firingquantity.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/firingquantity.cpp -o $(OBJDIR_RELEASE)/src/bpn/firingquantity.o + +$(OBJDIR_RELEASE)/src/bpn/flow.o: src/bpn/flow.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/flow.cpp -o $(OBJDIR_RELEASE)/src/bpn/flow.o + +$(OBJDIR_RELEASE)/src/bpn/node.o: src/bpn/node.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/node.cpp -o $(OBJDIR_RELEASE)/src/bpn/node.o + +$(OBJDIR_RELEASE)/src/bpn/place.o: src/bpn/place.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/place.cpp -o $(OBJDIR_RELEASE)/src/bpn/place.o + +$(OBJDIR_RELEASE)/src/bpn/transition.o: src/bpn/transition.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/transition.cpp -o $(OBJDIR_RELEASE)/src/bpn/transition.o + +$(OBJDIR_RELEASE)/src/bpn/triangularbatchplace.o: src/bpn/triangularbatchplace.cpp + $(CXX) $(CFLAGS_RELEASE) $(INC_RELEASE) -c src/bpn/triangularbatchplace.cpp -o $(OBJDIR_RELEASE)/src/bpn/triangularbatchplace.o + +clean_release: + rm -f $(OBJ_RELEASE) $(OUT_RELEASE) + rm -rf bin/Release + rm -rf $(OBJDIR_RELEASE)/src/simul + rm -rf $(OBJDIR_RELEASE)/src/interf + rm -rf $(OBJDIR_RELEASE)/src + rm -rf $(OBJDIR_RELEASE)/src/bpn + +.PHONY: before_debug after_debug clean_debug before_release after_release clean_release + diff --git a/bin/.DS_Store b/bin/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9f49df576945f7892a40e0707fb79bb3aff92ebd GIT binary patch literal 8196 zcmZQzU|@7AO)+F(kYHe7;9!8z0^AH(0Z1N%F(jFwBCH_u7#IW?7}Ar<iwlx+@{^!4 zqts{!jE2By2#kinXb6mkz+ejjMu>wraMb${*->&d1V%$(M1}yUd{BV2?HL@PbOVG2 zNii@oFo3%Nj0_AcumEBN_X8L}av-fB8l)9OgS0X*f>>ZPz*-p?p;{Ti-4KvI0kBbw z3}EdHj9{BV;$ZCzj9{A?7#Jbi85p59GeUbPj1cV%j1cV%j9}ZrMvfArAut*OXdwXV zyR$O5Fr+dhF_fb8-%lnL<YX3?7#Lh<WMXDvWn<^y;Nsxo<%$i?$S)5rNh~QXc1kRY z2Jr$COEQw6?2!EY95_2MDJ(O!JYGP=IX|x?F*7f<2&6nXGbJ@Cu_z`yGcP5-+$p~_ zFQpi44pf4JgOh_ZUO=L{+Q`^UN5R<AqE<(t+T7egN5RC{thSbuLtNF+)-xfuvZ}hK zwr(cGOR$oGfgi$$ld~8Y7?8Y}Qk<NVl%Jmil1CEGDK2w{j9f6Shxz;#%;%h3+}ykp z9-bav-ahdH0;R>NL8&>3C7ETZE{P?n#qk3C#TohKp2_)n0Y#~0nW^RB$@w{@xp~F$ z0)okjImx9ti6yCyIXS_ZRS?z5Mfo{70r|z5C7Jnokr5@S6(t}!kU=O?5mCkYMJ3K) z!y+=1^Yb98gg|!q7l1Suhou%3XXfW|a<1kRmr+#J(l@cRbH2haASfg(!p$9(nUb1U zl9`s7S`=EInNpGwnOK~hnwOH9mmXf0S)7@alNyqjn42o_o|E&6kboe+grtNthk!Ci zL}^lHVQFSbCD<rgISKBVl*E!$-~1GiVJQMzIXJ;GN^%ks(I6S;qSVBa)D#X5u&|oC z1b0YrW>u;{B2=Na4mWp5c4l6RKrtsotAQc6L}*T8QfiJs3MWLHsTsFKcp1b;0^U$T zD{F3vh~)g-+|<01VnIe7sIa|*ghU+3W}n33690nKywntd6C4~6U&u+gad1R}WF1pd zQd2mTLD3Du$_^SJih%*_ZDj`o2u}c10m(8LFgP)IF~l(xFjO*hGfZQc&#;AIE5kO1 zLky=Gt})zUc*gLK;WNWmhHnht85tNE8JQVb7<n1R7?l}S8Pyoo84Vb17;PEt7~L6t z82uRi83Pz28RHle7!w(j7_%7*8H*W97)u%J7~2>-7&{re7$-B%VVuvnfN>$?D#o3R zyBYT|?qxj2c%1PB<0Zz+jCUBHGQMK`3~?b7wB}>*h45h{<5$%5ol{%}9fD(;f;}P2 zfD^LjpiRg(`5>uRR7_k!RZGv<!qy2M{b&)6k|vRpAvo<p5*Ikp!4efX)~`rNN=eJe za?8WA0D9I4&CE+lt>6HqH34>rY9$#J4uKOK0vup2x4Mibr@&SY0Y)%aMqNgigF}D` z%;7eWG2#?R<Pcy6b7f4q%{c^8I0ab2Ty86F8%}{@P5~A$SH_;(kwd_nQ-BT3<#yqA z;}m$$DZoH5#WHX(;7+e687?tAWO&E$i{U>bD<c=95TiJw0;2|_9-{@L9iu&?6QeVu zD>#J)G6pe*FvdbtX)<FDV=iMJV*z6&V-;f!V=ZGnIHh(o_AvG_PG_9KIE!&M<6OpN zjLR8UGOl7=!?=}k8{-aW+C9p6j`1=iUBXkV4}=dR8SkK`*0SKDyqx^Jba0aprf8I= zO9(JSY>@!<|6LgvaE<>%RE?6OAut*O!!iUISzLl$obZ&upuRS!Kb-*eKBy%E>W(vl z`sEOPASIx#J-9p02$@s_t7c??^yC>CAU%0T1_qGUfg1=&%uNMXwWIa_X#EdPp(B$3 E0Pb5G5C8xG literal 0 HcmV?d00001 diff --git a/bin/Release/simuleau b/bin/Release/simuleau new file mode 100755 index 0000000000000000000000000000000000000000..d60f74df50c333b2e52f788fdd5a0e9cf9dcf8c7 GIT binary patch literal 305464 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Πmg3VXU9LtdO2{J>;+fn%I(D`;KBzw5}4tD zF9XAq9smA=&SOFEgM-)Rg8N^fl{3X$d<L#y2f;gFZjklnEPf0O4<s<lXV4kJJC322 zy9Ry?3`chUgU`K#@~n#=1H*xx|FDkvC-^ZiT-o^#V-E%>FV%p~7~c8sKX{irIE{ny zl0P^MKzU$}9|MELu75<&37qi*oelkuYI6cIptFtlW0q5(x?jPAfgxxAzyEEZG1^QO zaN7?(e?=jW!#i?=$8bT(1!?YVXEb6?$DkQ)t?DE`$bMWFSx|~#0FSfJ@L*tQ+5hi< zJIG#Mn7!a}4M@K~20q^aT7m+uyFl}_Nqo@xhL6f1CxFKV|A5YR-v94EsQds4f@pyN z28JVOVk!X)3<viA`|l1?!~k)JMF0cCpZ)*-8$-(lsNcbE098qU(EJWEI|p<I^ud4d z^{SvUsv&@ZLFC}S|B|TYfX8TD_zXgjje+DwM3Dt5R6zCrkpKpU4+sB2&h`SQBX2&1 z5J;Z#=7wf2AILn#hX4kKDTn_32d%9F<rh?U2Y`lA5rrT$f2e>C1rWo`AD}a;B`%@n z572qlQx2oHH$Z1sFF1_Z-T<ZXhCl{}C5Qk0zX10?V&4ICC}`fx5quzkA2;M&!3}{7 z3@%3z<w7$PlPhSV3X~7e1TrvGV37mmwHJX53~P@5`wuz?5VGzIl-D5V8iM3Gf*2Uy z;E)HUKG3<@I>-L~2c5?V(%;4eUvJw08zce6G3Y$)CCC0j){;Wk^n%XTW;l*oA6Eo1 zF#I|8559f`q_+ojHaD8sf*=NlFUL^zZV6&w_;3u7jzD@(pqU49^Bt&ph&96CHA|p1 zMZw5!W(j6sa5(<&KPWyxNgQOJL@)zG%yCrr=>#({L>&JIKaT<wZVtf=3@yk1LDo8h z)1DWfLLRsX1LyaIU<QUI$N&A$0~rh+19Atgn+9c(Ft8h(Aagby!3+#<j{p0g4Oa)w z(<tgd?%EK{z+iF$HGLfcx&OpJ$l9zxP@Pi5$KiSyd>$3({PB_#|NcJ)nG3E*;9=km zDJejsTii?@aE=>y2H0Vs*)~YONF{`ULE+@T|3x4(z<vO`4V*_off)*}9uf14At4M5 z1t<Ug2VWkJMST*Q`j!v|h65-6{bz;e0c7(7m|h^M2gU1_5C(<?r~ds1pGSx6rvRo! zFsFmm-3eh}usHqi{~wUMQPn*|RtGv`UEs_=$XFq=I)iGMGH^dk2XyxOnScM;ak%pp zk~=|lL`*0HgT~o^{||%g2e%QxYjD7GEZ{bR7heL?d~lTvZ*hS7AX7pa7%m86mN#oa zXT9G<?Jpe&Wnd7w`445U$(2wBh6!i?{Z|Cp3(bR|bK=*WMNQ9tLKzrVoJCDb0$~gc zTh3yZRiM#4oiGN59cTYR#<{`a1YJj^0IhT&#~L)j0u8j%Ga-zD!R6e)|BRq8O9JiN z#&dRw1JhA#2gHH;Dl5Vm7<kVA`wu?&4jh(P<^c+!?Kk+`K4h=jlQ0H`gp2?FKL>55 z!PU>1gx=5b0QXfC!WkGuuKk0YRRhl7aiHQByl2WLoPj|DiySEJMT9dj*j)PuUtf*X zSBZs%4@g}@I0Hk=HAEW-s?Lp1fyo=D4wUa#gflSgx%Ll!7A#0?PdMlfAXKpn;S3B{ zuKk10m4VXJlW+!x1N@lj=}$NV!;5RE=}91hf#JzDL_Y##k4gjs!-H%8;CnYgb&W*? z1H&3LGeOA>q&_5qf#Cp}xfu}<_ruQ50I92qU|`sB?H|g1(g_g|_amQ4u>{S2klq~; z3=DU!q1L@;A{ZEMpou+znuol1^h*Q-!v!RDpneWVBm={lYybWq0Hsqz`U0QJ1McU5 z3c5J7zJ(_@(|(8$JjH>=U_jv$0WyydHOyh*QxeI*pl|~<+&dx}7-VjshWngI1_p^6 z{~%|zLi6#4NCpOz8~^^BgA9X;9f@RMNVxIuzZ{a-jYtNDoExa&^Cl8>R}`ukLlgr; z3Yt2RD2RE;VWttqzz~C`&L)b1Ap%V-Ac}z@1Wha@ih&^jO$>BTgb$J!C=Pm}7#KWm z{QExv*O&rmPiY-AkHbq$Pj2uUSx|QqDHcHK{!SDFLkBNv9DwTVFHsB(1-JkG2k)K+ zuP>?M0<8cA)p($|6NzSE*l-)O&jLz!p!*58-2V3;vSR_#CUc2qVEAzRANV{m$leYn zcTgb#Dz_4%85m6N{QGYKO;<fk;PxH(+(GDyQpgn0Lr4Ye1Ud>C8m|+S7#L15A=a9J z+zz@&L*?#2$l8to(3~cC&JSD{gWPvSiGg7b6ZAYms5wuf85kBZLB?T0Nd%<sM>GS& zJTx&L(48E2p=}wcUWFJ2h9ziXCNT^Q7w)3A$vk2h7|z^9O}{ZQ3=AjG)D^@qFdVu2 z@4r9DAy7M7K#kISsA4l>7#M8sA<8k3o7coJFnAz|fzB8?5W~O_a_`^&<IsLRblr_7 zd|e}W{iHK!o(!~y|0{GH*#-4zPsqMxo>&Hk8xQ{d-vDwOq6`4n*G#Egur=7AZOP#N zlT9oGL&QUbpFwE{bdO00H)@S%HI4oLk|)O_C%%fO)W5Y?YkVi_0=9-`LOD`FWK zbkM~1#4<2wJVdSgFF?&h-e>v*Y945v2`GKS_L+j*%Mi!FVDb=J--GM7C{WS``%fm0 zfuV~5u?H2@J~oJhxYrt*o}ugRAYrr#9!8#^aVe1c1d#cU{{44=s)we3$iC_gkTmZK z+H4O!H+@1J1B1)se~@!N!0ssly9eafHF2Q3k1*vx_2`K>28N!;{~+fyg4-tGb}p!s z0~ynTjtzc@V_-P)7!kIha)KqEf#CrsYMg=MO9pgT%xgq^f!tsa&%m(c@jt9%9X_Bt zR~}=Q8=$seMmz(<p2z?G?*b(Tg!^3h44|j+Lbl|BHX1`Fk)dbhEr@4e;QId?JVXo9 z3Ub$$cm@W8Cy0JKD4b8kGcf2p`S+igcmet2M?3?A%~Q;=4Uk!XA{ZDPo<hc`SWXIK zjBV6Hq77Vbfx@rFnt>tf-*52QW-KcqDGy|h3#h(%3dz?jGhya{+xCv2Rdoe$b0Fu( zpRs0Ou>1ELJRZSP2{8xc-z5nQ3<XaS<qc@v0qCBdoTvZ(>%r3%q8xPLGXO6=2W^{x z^h!WygDALx+fz=EbNqiKFfhbCLyTjA?BN03;qwe(52(CVNMv9LdG_zWDJby4>Cux< zAr;cU1L<){WMC*k(gSi^NFoD6!Lxt=`LMdpf$0Gkct;1sY2Mr}d<dt3$9SeBGB7wi z|3~y%N>F^BNMvA$VMk5FASZ*|_#}~mVS&zn`1}dTUq2EV7-U}l1FvHSl?llE5kY>C zNMc~HdHL`EZ;&Aopn3)oZ=lgc$X-my5#nCpt#ybs!=QT4A)0~V&&z-R!$EU=TLqER z5IF9=_!^j))j^9wA*Z&06BG1IZIG2nV`Ni35MyKwOwd6xP`U%9F}Xj`^b!wQ9R{is zt|T!qJb3l*e<Nz00A4$Rv93ITX*<?qUA!RUbqdK03@UH`LC$^z=UZ@}2ed!H2b`W9 zA!n_7Br`C?y#4pz9TevXb?$s<drUxO0jOSVc=zvr8z^kn3t$Z!CM^2_LHjK1enb7+ z3W{0C*;SxBp$@$N_rDs8f5CIM;I$%-pgIt=wjZ=+4a+gy9^n0f0x1j(Uq1f(?*@tl zaC!%wh2q5x8e{^Mvj!;)3@V@g{r>@#N1Qju^a2(hp!knSVPN?4>EHi{pzr|KrC9dt z?Z>`nZ%PUS!-g;a{!hczUxVz~yASHIIU>zWfeujzrQItj3=9H4|NWm1I*b>szXv{F z%^kdUua^~V&mU;O6qJ`lQW+Qu82@9;Pl5fP%D_;<_#dzTK`|4N%D~{m^dDs|GAEUR z!2?aKA(er_1x;*9Dg%Q9k{Bqzg6`w8Vfqglqw)Za@qqTvd2>5M?{7E(wGVt&D+2=q zsII>Qy1R?%Kcrm>j>~*5&{3qW;L~j&b5jgy3=Bt@{zL9~0jFDcK7~X``3ACAA&r6I z3e*4p@zD4N?-Q<t$b-gj9nu&WM412op9xKS$ZG(>^AF&&vp`EZYMA)Y=O1A0zcdDh z0@nYKIu$y;JR^;Pp@;SV|4wN7fsWIH+qt0fXD{+TU|&dHJ(I@3@Ph3><QyNcU!uS# z*7}0|>kDp2WH2x=+=*vk5MclR{}X6Gj4LlV|Mi2`twGNeb_1Qe2F^3!Jt3f3B^Rt^ zgflm@IcOob8}>8pL1h$Zym{95-{84smY<LlkU?%pNMK;-;rjpImz{xu<s}a>ZV1Qf z1`lrLxu8ZZrW<@fZ7`4<N&*=e%wTR<32_6c?EC||t4;9#|9(*1g2(B=btt%eW{QJX z&Y)}sZV!U)YTF@*h$m1w2i@CtMG%qBLF4fu8KCj2|Np`Jb;0ofE;HTv93mlxf`=R- z=jAtKFff=1|NrkyApImTRbpP#;0~D=Jd(k{;2`?{KLgYZj5&Bv^1F)OZ*+&81DVOd zFh%wMf6$#kka2BK*qZt~u<{I)?*)<=819Ju|Njs)?~=<6jxT7M1c#S9p8<HT<%uK% z!>g~*_>Kd`0A!6J=sr3fwf~TIEm~M3pI-;6A8L{q7!t()|NjTFO9{m;X!<t*?L9|K zgg8Rx@e-sM82Y|K>xb`<-aE+cPcj)81SI|w+~dZR#lUbw;y=b*9jI?Ekj%hvN8<ng zV9<GUi@Cu5hxWC=^(wfY0r$1Q^$e)5#e@A=U&xw7(0!nvzWfG{ZLris+zPU%BAJ2V zitPXYFF|=TAH^P5KJ0td=7F*x=DCrOePN*cjCXy3#)mz^o(G`%TJb-)jm4smVh`9q znC%4S%b;wAX%A#y*o_bdhN3Ufu>S%X<pR|upnCvW{{4oWaRNP?8kF5YW1}^oy8u=G zL(bm@pE(IW*W8s)p_c`0KR7(Wdq&*(9P+RYje_&#k!%Kr29^Ktbu=LJ|IgNCR5{7W zdX$CX9V6>n7KWdUtUFm4)-Wk9WMTNj#5$FQv5kdwAq)7tD+UIJ|Fd}+S)|+;5PV%m z)t!v2%h?$2F|uA~V|dBPx}S}qk!c~*X*PzVEUcT^7!R|ioMwY+_&-~ak;8zMfgz9; z$qY?K`7MmB_gNWkGO`|LWq88KdYP5s3*%g--K-2dSXkGyf`^46?giOzg`!vP5F_gi z7KUextOr;aJ~FbNVPR-ws^7xGu#A~?1q)m&)a@P!z5f|cGTvr6&dR_rmxpz~8^cqc zC2R}~(}Y?3-59nBzZYX*xT?ka*o|Q~==8*A+N{^z7&>(<85rK{u+Dd9=+|{%VEC%b zI@^t5hF%jZ1H*n}*57UnH;s2PGBEryWj*c2aKda0BLl-s3)anU3_C3p85q7>ux@u} zm~Qz3bS;WC>tuI^J=U9;85nx(S>L-cthbM3U|8nBy4;Q7q(c}3!x~4{)$R;u92FTD zCONUTyEANZ+Rw<qFxQ2(*^Ob3ixdMxlPl|CcZP+o;S3D_|1+|3&jJ-~|7UwL+HGfK zJ<r2%hmrL#55sdt*8e;V-<cjWe&%6#!NU5ShoPI5^)nB{G*;H_JPhkuKe2q~VK~9X zdYgywGIz>n9%y92;#(Lc%=m0sL3h8;V_~?*C=a%mg_{*ji<q)9FgUR8VrKZu$O^ho zmGu}i$XzVlqF{MRi2NsJhFgrFHCRln|CkwmFjashVT$-5iY_uTYycVZ|34$lcz$zh z28IeyVm!#Wg9)k$Vl%%hD+5CS>wGSTdyI?NP^6wRhO#m+B(TntWytAcWMF7uV*Mt^ z(8B~`FJNYUCC9La8N@!o!g^1R;S39i{eYGAk{rVuRuH>^o%NU;Lk~NMy?}#tmmI?y z4iNhQC+j*nhBKTX_5&`~MRE*pxIpX%9@c4c3_Uy`_5xnkE;)uZydd@gKGuJ-3}^U2 z><9d;pJW-{@PpV5f~?PE8F~cYF)=VSh_K$0W#|!k#ss=;m-U=1LyI`5^*=#^^^h#X z9Eo|13=9V(S+~hDoRI{nKOn=pN|xb_j5yfGtlUc>p(5A~3b|>FtiM<o{xQyl2*N^9 z5fZ+O85#Wf85mMncQY~+^D{7XFtV;^WS9ri2o7>pu#sG#^DKfE@O<I{$0I)^wE0X} z85n$7x3Dne>|qA0gBi}lXV1V8%v!{d3sDIZ=h9_mVA#p1IGYJ<4m7=hMSn9I??Vxl zQ8~%Tz|hLXdW?l(8q*O*28K_}te03Anpx1y)MI5}@Hxk{1e(SmvYa5ZlPV{m7|E%~ z%D_-vxfVrGL*f@B1H%j^)?XY9OPJO%F)-X<VV%Uu@Pq}#p25!A#>udRT@30!NO;KT z`7kgvFtYw-W0=IagPDQh0t@R$HijoG9k4)#q;x@5&_!}57+L?aFkEJwh#E*nlAz0G z8Cg$qGE8CI&cwiQk(u=^C&N=_Ee3|EEUXVX8J4k3Wno}A$iaG*li>^pKhz1PU|L^a zih;q;d^!h1HzR8|2g7v6UZ&|B46B$~|FbjfV^*2Y!SI5a^)oxeSLT<D(>cK5EeZ)6 zF+P3<24zsHw&Z7E@ME3D$dCe&fn~m+d~F7X1&pkdI2blCf|kcIv9@tAOknb2V0gg9 z`iq_61BiKmne`nz!v*Fn28IJHtdH0kE`Y8vU%<+Gjh$fwD@Yp~>nV1I32dPB3QA23 zrC_HEXy0XIU|7J!`jd%a9TUuE2rZy}jFEw%lZo{a6T@^2xow~#m67!#6GI1v+)Yqf z%EbDOiD4C8<n}Q#Ff=i--eh8!fMFjk<i0a9FzjMtox;p;0>i%dj0_B$m{@z584jS! zNwG38=(FZASg}?y_=)F%(}5TytVJN{AfLgCpMk-jwVELdA`VLhJfJ*e!0N+b%^HEM zj|Za9nZXXG9zuij@k>U<(<u21EV`P>{uhd<jAjA@Lq8+yGj@hqjG!9~x3I9@VrSUT z0y=d7lvbd1g@$G(1H%kP)`NTuiy1#NGce3yW!=ihu$&cig6>)l)|Gq=J2+Zc!08I+ zZc)i(28IcYtXCNs<}>m$FdSlJJ;@060Mt-UP)2a5`~($*xL!kI5fcL_{MK_ZoMF1h z#K5qDmGw9m!yZ-;djSXQZZ3v39N5c&yX*{;7+)|mFf_2TUSwyO!V0gKVC4Yl0*}*- ztn*nIt}%i()`PtWIwT0xni<8TAut*OqaiRF0;6Cw1V%$(Gz3ONU^E0qLtr!nMnhmU z1cp)wB;-R}y8*mmkAdL>lr{ign##aX0HrTLX@N9|`T!_B0ZLzh(gNUvLl_tovLNaj zp!5MK%>dp2!oc7Fr5m910VvIo1JUOIr5m910VvG?J{*OC!2wD)K<NWengP5Kg@M5V zN-IG9cjo|T(JceRLn!?mN`HdVKcO_!L5Mm5C@lx2b)mE+ly-*F-cULmN+&_-0w`St zrCXtNAC#U6r58i#HBfpRl->`ePeSR7Q2I8MehH<2Kxwu^5O?!KX;CPx0Hrmcv<Z~9 zg3``VIv7f)K<Qj4T>_;$p!8fQy#-32fzmgj^dl(!21<X0(tn{e^I?cPxuLWul$M0j z%1~MlN*h6GYbb3GrM;kZAe4@T(kW0n14>sw=^7~A2Bo{8bRU$S38hy+>8((DCzRd` zr4K>r<52nzl>PvvIgUX5Cj_O%p|lK?R)o@OP}&emyFuwlC|v-h8=-U?l<tPo6QJ}| zD7_p?ABNJGp!9VpeFsXvfzp4WG}BRtdj+Ai7?hTV(h5-807|<+=@=-T2&Dr~LCh(D z(rHlfY$#m-rCXqMCzS4k(u<+=PAI((N?(D}hoJOLD18q~KZepTp!8cP{Rv8gX7WHK zip(*H`wXD80+cp|(pFH~9!k4FX-_B}1*OxVbODqGnT?DkmVg#@F)$c>gop+}=>jO- z@ChOgBQ>Dv9iZ|FFdC}P;WJDngm!?c{{UWy$G{)}I&>c*1ttTa@(ppIg+&Yu6QDF$ zk^ywDJH&k-;vw=52@o14{{pJN0Ce~d0|P??ly>NbsG9)g!)Tbk3(FwpGTeixbAZw? zd5;wk`2&)Wcz6J%4KyHp1}QWes!?JkRG%?K{sNSSN;7Cc<v+m0O(5!E@)l6}0yBts z1C)lzdqCwKtReCXp!5MJ2p^^{0;=wUGerCYls0gI@SDJwi!d-WK*bk8X@!fB@GyYV z3&58eFfeR@(hgAZ04Tk{9b(=BsDA{Y=5K(ScK}KkxI)yy+*bf~-v+4u2T=Ng2SnWg zDBT8iXA<auI|c@ZI4B(jr5T{=9{5A_!OS0}M|KD_+(1na6QF!pc?S!f2X|1_S=>eC zGdw`$e|QMt!_qIzoC0V$G@%NTe>Onr2h|WhEIlVc%OhOr`2tj*15_Q%e2qsCdtv;9 z#}Ga&pTop|K;0n#S{wrs+y${;U^awKfaY65`MzN$MEwTPp->DA4Cwhj09w8loP(&t zneP`t<QsY+w7@h7y#cf&gMoqJKo5jp0Hp<>>NfO4#2qF;=z=v6IsmF)0klAefq`Me zA&B?{sCzzag77y?gwPW}mpOp!*$CkWY=+Pblc6*yj2IXgE<nTcz;a0W4HahafYuWm zpyBoaN;7~ix(1mGEq^|MX52yMK+8#3Ic2~Li6>Y&6(9!TU$_Oazu^jmhS_%>w9pR5 z0o7-(AnMWM`2o~j2_HZ!kr)^np!A2&5dHzEJ22uIsxAOZ6Dr>W7$Np2FhFSZc%JYH zV&8`!5c&bkTqxZDbq`G3;3GsG%!>=4{zK1Cuy}X?^@jj794A0&Sbo|7t(PxA)e#E! z3E+#j85jfvApU{5gW)xV4{J}r#2-M#(ZfFh+CFH2wg(nKX$4(~IUAt$p#xOB07{cu zzaD_<!&SdFXhQ6ppar2}?*0IEH;k|F235WQjlT_zzX!^PwKrhqoWLRe;4Q>_Sos4} z-vO=XFSJ4A541z+BnX`_8A4;EQ)oVewL{R$BZC--K7(io{Q+A4D}+M$=;`zTv>l=l z2az`jgwPM7AhZGa;Cj-_qX#Vz{SLhl+5of$iGhIuRvt|Vf{0%TgU}67_Zj3t_z4jZ z8de^`N&|G-A1VN)7>YrADHz~OEEy(1`H<D*&`VJn7#Lvp4QWh;*aO?g{bMGioRfw| z)B`9Dx~dz*yfF(R58878;zNyR`1<cZc!XjB#5e}n3X2ZV*?9~M3~V693=9k$5bX?* z6}}7%%}@qp1vX@#E=VcpC_oSm!%$-xeyo8Q04psVpbh}7p9iT0T^|La#X$rE149P% zFdUfp1E@!!+88=O3+x#f7$7Tw5%$COXv5U~{txjVBLf3i=pU5-0UB`sp?sJ-KS23B zQ2C!wKC~Kwx{i9(ja86vK{wF=bm;}Co`%u^P&xrh7eHyy`92`M6QKMBP#U!U8zg=J z%D(`mA3$l)z6p>#1L*7>&^{3;tpKGBptJ*&2A#VDQl9|j7eHyy`8pu+2~hq5C=EJC z2PA#~%D(`mA3*63P?`a}Nt}T}07@%BX#*(j0Hs0a-hj+Yfbt8VbOV&00Hs0a*?`n- zfbtJO=?hT$0hIm#r5PaC!!rm#X$2^40Hs0a&w$Jefbv1-&4Bm?P<{iHo&cp6Kxxo9 zG9Yyap!^F^8gyO^Nc;no&kzFQF)#=~X$2^40HqzEbO4l2fYJp}x&ca0fYJ+~^adz> z07_qg(hs2Y2Pn+|KCqgBK>$iCKxqRg?Es|%pmYM1E`ZVvP<jHCUI3*bz9OCE*npZJ zK;<J0yE{8uDQJWymFAU{Dp=~7=o#o5mV$YPbw&ny1}1t&nh<dY2EF2p;*z40#3Tm2 z%)FA+q5=lJy!?_>z4W|Ny@I0rg4CjtN+hAA(#)I`-OLoIkfW2QZb@P~16X-RVsQq8 zUP@(Nab+%qE-8Y@l%*CGXXfXjaN>&?^omk*5<wcEtb&{pkSj7v81xEqO7zn6p^W0x zWCp#G)QS=Yy|m1{Oa{H8{FKC!L<YUojQF&o#N5>QjFch-k3lazIXOPHB0067B)%ju zDJK<TYJ6f*QDP;;3>X_^4#*jLMfqSSC+21*Gw6Xt8T68hiy8Ei^K)}k^GZmMAT%AI z@*fmGuyS1jT9CqMSbYQ222u-SgJ{q$WKbCo({BOQ52Hc*>_F;Z7+i?MI1CJ+>vb8B z^~0)P7!BH=gQT1RHFYsCSTZo6=&ym=52MlTN7oOkroR3EpAU0CtR98YpuK1y`{DH{ zh=YVd#ULmQVftb9ER1e|*0Uf#g2E2wf6(3+kTH=A4B(bLOh2sNhS9Kk8l)D4L1utx z7)}K3RX}n-tlopsuyzE@{V;oAG-#RwRHwrDuzD3vLoEWi9~87O_d|slK<9jd!W5<- zR?ov|SUnH3AEqDXfABed3=9mg`)FY81{e)%XMpsBnh@yvL3aay!UQA_b`!LIWPsAJ z_7qqSv|kLyfYLqCHXBU80#qN2o&al5LDhry^nsW#dODi^4bbuvM#I#B^nfso52Hcn z#UZ;NbY2xm9gJ=uVE;-q`$7B4LHc3zQ%g{+fkYq}W-o-tzyP`{2ibmDyA(#l+N&`2 zpty#yK{V)22atYP{4>BZ4wU{5xndrq6pYdHBj_$fWc@#2{T3*FM+~eDPN3U=8tQ+T z{Wn-3D&RD1UJz;mEd4;a3|G<gZzzE1htZX=1}anoL>9_nU|;~<`2=ce!$KL>j{ngK zQ3=a`FdZ=aVKiuXo*!BUfYiX+`8T>C`eEuoav%)j!)VYQSD^5N+5Z6APj~>;{{v(= zNFx-Zhd&P^q>lj84{OiD+@SysSWx~483D5wmX2ma!w;q()=&5`2kL&91V}TeAA&}U zGD7-HaAmOe!vctY^zt8OKhzioX=uj)rr!aoUj?dv1E_F@DF(I2k=P(6=v-J(_<_!E k1My)Pre7N-0Hr}{K}=*CW;aM2hW(-TYr+&lCD6DG02I+aZvX%Q literal 0 HcmV?d00001 diff --git a/examples/batch1.bpn b/examples/batch1.bpn new file mode 100644 index 0000000..74da025 --- /dev/null +++ b/examples/batch1.bpn @@ -0,0 +1,47 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {8} + steady marking {8} + output arc T1 + output arc T2 (3) + + place CP2 (continuous) + initial marking {2} + steady marking {3} + output arc T2 + + place BP3 (batch) + function (2,4,5) + initial marking {(3,2,5)} + steady marking {(5,1,5)} + output arc T3 + +transitions + + transition T1 (batch) + flow (1) + steady flow (1) + output arc CP2 + + transition T2 (batch) + flow (1) + steady flow (1) + output arc CP1 (2) + output arc BP3 (2) + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + diff --git a/examples/batch11.bpn b/examples/batch11.bpn new file mode 100644 index 0000000..ba81805 --- /dev/null +++ b/examples/batch11.bpn @@ -0,0 +1,44 @@ +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {8} + steady marking {8} + output arc T1 + output arc T2 (3) + + place CP2 (continuous) + initial marking {2} + steady marking {3} + output arc T2 + + place BP3 (batch) + function (2,4,5) + initial marking {(1.5,4,4)} + steady marking {(5,1,5)} + output arc T3 + +transitions + + transition T1 (batch) + flow (1) + steady flow (1) + output arc CP2 + + transition T2 (batch) + flow (1) + steady flow (1) + output arc CP1 (2) + output arc BP3 (2) + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + diff --git a/examples/batch111.bpn b/examples/batch111.bpn new file mode 100644 index 0000000..9af0b1d --- /dev/null +++ b/examples/batch111.bpn @@ -0,0 +1,47 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {8} + steady marking {8} + output arc T1 + output arc T2 (3) + + place CP2 (continuous) + initial marking {2} + steady marking {3} + output arc T2 + + place BP3 (batch) + function (2,2,5) + initial marking {(3,2,5)} + steady marking {(5,1,5)} + output arc T3 + +transitions + + transition T1 (batch) + flow (1) + steady flow (1) + output arc CP2 + + transition T2 (batch) + flow (1) + steady flow (1) + output arc CP1 (2) + output arc BP3 (2) + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + diff --git a/examples/batch2.bpn b/examples/batch2.bpn new file mode 100644 index 0000000..78f3c99 --- /dev/null +++ b/examples/batch2.bpn @@ -0,0 +1,47 @@ +// batch petri net without discrete nodes. + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP2 (batch) + function (2, 4, 2) // speed, density, length + initial marking {(0.5,0.2,2),(0.3,2,1.5),(1.2,4,1.2)} //length, density, poistion + steady marking {(1,4,2),(1,1,1)} + output arc T2 + + place BP3 (batch) + function (2, 4, 2) // speed, density, length + initial marking {(1,4,1)} //length, density, poistion + steady marking {(1,4,2),(1,1,1)} + output arc T3 + + + place CP1 (continuous) + initial marking {5.5} + steady marking {5} + output arc T1 + +transitions + + transition T1 (batch) + flow (4) + steady flow (2) + output arc BP2 + + transition T2 (batch) + flow (2) + steady flow (2) + output arc BP3 + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + + diff --git a/examples/batch21.bpn b/examples/batch21.bpn new file mode 100644 index 0000000..cbbbd31 --- /dev/null +++ b/examples/batch21.bpn @@ -0,0 +1,47 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP2 (batch) + function (2, 4, 2) // speed, density, length + initial marking {(0.2,0.5,2),(0.3,2,1.5),(1.2,4,1.2)} //length, density, poistion + steady marking {(1,4,2),(1,1,1)} + output arc T2 + + place BP3 (batch) + function (2, 4, 2) // speed, density, length + initial marking {(1,4,1)} //length, density, poistion + steady marking {(1,4,2),(1,1,1)} + output arc T3 + + + place CP1 (continuous) + initial marking {5.5} + steady marking {5} + output arc T1 + +transitions + + transition T1 (batch) + flow (4) + steady flow (2) + output arc BP2 + + transition T2 (batch) + flow (2) + steady flow (2) + output arc BP3 + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + + diff --git a/examples/batch22.bpn b/examples/batch22.bpn new file mode 100644 index 0000000..7cbc0b5 --- /dev/null +++ b/examples/batch22.bpn @@ -0,0 +1,48 @@ +// batch petri net +// + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP2 (batch) + function (2, 4, 2) // speed, density, length + initial marking {(0.2,0.5,2),(0.2,2.5,1.5),(1.2,4,1.2)} //length, density, poistion + steady marking {(1,4,2),(1,1,1)} + output arc T2 + + place BP3 (batch) + function (2, 8, 1) // speed, density, length + initial marking {(0.5,8,0.5)} //length, density, poistion + steady marking {(0.5,8,1),(0.5,1,0.5)} + output arc T3 + + + place CP1 (continuous) + initial marking {5.1} + steady marking {5} + output arc T1 + +transitions + + transition T1 (batch) + flow (4) + steady flow (2) + output arc BP2 + + transition T2 (batch) + flow (2) + steady flow (2) + output arc BP3 + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + + diff --git a/examples/batch23.bpn b/examples/batch23.bpn new file mode 100644 index 0000000..9af3624 --- /dev/null +++ b/examples/batch23.bpn @@ -0,0 +1,47 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP2 (batch) + function (2, 8, 1) // speed, density, length + initial marking {(0.2,0.5,1),(0.15,4,0.75),(0.55,8,0.55)} //length, density, poistion + steady marking {(0.5,8,1),(0.5,1,0.5)} + output arc T2 + + place BP3 (batch) + function (2, 4, 2) // speed, density, length + initial marking {(1,4,1)} //length, density, poistion + steady marking {(1,4,2),(1,1,1)} + output arc T3 + + + place CP1 (continuous) + initial marking {5.4} + steady marking {5} + output arc T1 + +transitions + + transition T1 (batch) + flow (4) + steady flow (2) + output arc BP2 + + transition T2 (batch) + flow (2) + steady flow (2) + output arc BP3 + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + + diff --git a/examples/batch24.bpn b/examples/batch24.bpn new file mode 100644 index 0000000..68b1fd4 --- /dev/null +++ b/examples/batch24.bpn @@ -0,0 +1,47 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP2 (batch) + function (2, 8, 1) // speed, density, length + initial marking {(0.2,0.5,1),(0.1,5,0.8),(0.5,8,0.5)} //length, density, poistion + steady marking {(0.5,8,1),(0.5,1,0.5)} + output arc T2 + + place BP3 (batch) + function (2, 8, 1) // speed, density, length + initial marking {(0.5,8,1)} //length, density, poistion + steady marking {(0.5,8,1),(0.5,1,0.5)} + output arc T3 + + + place CP1 (continuous) + initial marking {5.4} + steady marking {5} + output arc T1 + +transitions + + transition T1 (batch) + flow (4) + steady flow (2) + output arc BP2 + + transition T2 (batch) + flow (2) + steady flow (2) + output arc BP3 + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + + diff --git a/examples/batch25.bpn b/examples/batch25.bpn new file mode 100644 index 0000000..24a8c90 --- /dev/null +++ b/examples/batch25.bpn @@ -0,0 +1,47 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP2 (batch) + function (20, 80, 10) // speed, density, length + initial marking {(2,5,10),(1,50,8),(5,80,5)} //length, density, poistion + steady marking {(5,80,10),(5,10,5)} + output arc T2 + + place BP3 (batch) + function (20, 80, 10) // speed, density, length + initial marking {(5,80,10)} //length, density, poistion + steady marking {(5,80,10),(5,10,5)} + output arc T3 + + + place CP1 (continuous) + initial marking {90} + steady marking {50} + output arc T1 + +transitions + + transition T1 (batch) + flow (400) + steady flow (200) + output arc BP2 + + transition T2 (batch) + flow (200) + steady flow (200) + output arc BP3 + + transition T3 (batch) + flow (200) + steady flow (200) + output arc CP1 + + + + diff --git a/examples/batch26.bpn b/examples/batch26.bpn new file mode 100644 index 0000000..65162cf --- /dev/null +++ b/examples/batch26.bpn @@ -0,0 +1,47 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP2 (batch) + function (2, 8, 1) // speed, density, length + initial marking {(0.2,0.5,1),(0.1,5,0.8),(0.2,0.5,0.7),(0.1,7,0.5),(0.4,8,0.4)} //length, density, poistion + steady marking {(0.5,8,1),(0.5,1,0.5)} + output arc T2 + + place BP3 (batch) + function (2, 8, 1) // speed, density, length + initial marking {(0.5,8,1)} //length, density, poistion + steady marking {(0.5,8,1),(0.5,1,0.5)} + output arc T3 + + + place CP1 (continuous) + initial marking {5.4} + steady marking {5} + output arc T1 + +transitions + + transition T1 (batch) + flow (4) + steady flow (2) + output arc BP2 + + transition T2 (batch) + flow (2) + steady flow (2) + output arc BP3 + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + + diff --git a/examples/batch27.bpn b/examples/batch27.bpn new file mode 100644 index 0000000..d57f233 --- /dev/null +++ b/examples/batch27.bpn @@ -0,0 +1,47 @@ +// batch petri net +// bp2 > 0.5 +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP2 (batch) + function (2, 2, 0.4) // speed, density, length + initial marking {(0.1,0.5,0.4),(0.05,1.5,0.25),(0.2,2,0.2)} //length, density, poistion + steady marking {(0.1,2,0.4),(0.3,1,0.3)} + output arc T2 + + place BP3 (batch) + function (2, 8, 1) // speed, density, length + initial marking {(0.5,8,0.5)} //length, density, poistion + steady marking {(0.5,8,1),(0.5,1,0.5)} + output arc T3 + + + place CP1 (continuous) + initial marking {5.25} + steady marking {5} + output arc T1 + +transitions + + transition T1 (batch) + flow (4) + steady flow (2) + output arc BP2 + + transition T2 (batch) + flow (2) + steady flow (2) + output arc BP3 + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP1 + + + + diff --git a/examples/bp.bpn b/examples/bp.bpn new file mode 100644 index 0000000..8bd37f0 --- /dev/null +++ b/examples/bp.bpn @@ -0,0 +1,27 @@ +// test batch transitions + +model batch_transitions; +length unity= m ; +time unity = s; + +network description +places + place PB1 (batch) + initial marking {1} + output arc TC1 + + place PC2 (continuous) + initial marking {1} + output arc TC2 + + +transitions + transition TC1 (continuous) + flow (2) + output arc PC2 + + transition TC2 (continuous) + flow (3) + output arc PC1 + + diff --git a/examples/bpn1.bpn b/examples/bpn1.bpn new file mode 100644 index 0000000..82e9197 --- /dev/null +++ b/examples/bpn1.bpn @@ -0,0 +1,17 @@ +// batch petri net + +model test; +length unity= m ; +time unity = s; + +network description +places + place PB (batch) + function (120, 200, 10) // speed, density, length + initial marking { (2, 150, 4), (1, 100, 1)} //length, density, position + output arc T1 + +transitions + transition T1 (batch) + flow (4000) + diff --git a/examples/bpn2.bpn b/examples/bpn2.bpn new file mode 100644 index 0000000..8bd0f70 --- /dev/null +++ b/examples/bpn2.bpn @@ -0,0 +1,21 @@ +// batch petri net + +model test; +length unity= m ; +time unity = s; + +network description +places + place BP (batch) + function (100, 200, 10) // speed, density, length + initial marking {} //length, density, poistion + output arc TOut + +transitions + transition TIn (batch) + flow (100000) + output arc BP + + transition TOut (batch) + flow (10000) + diff --git a/examples/bpn3.bpn b/examples/bpn3.bpn new file mode 100644 index 0000000..e146190 --- /dev/null +++ b/examples/bpn3.bpn @@ -0,0 +1,26 @@ +// batch petri net + +model test; +length unity= m ; +time unity = s; + +network description +places + place BP (batch) + function (100, 200, 10) // speed, density, length + initial marking {} //length, density, poistion + output arc TOut + + place CP (continuous) + initial marking {2000} + output arc TIn + +transitions + transition TIn (batch) + flow (100000) + output arc BP + + transition TOut (batch) + flow (10000) + output arc CP + diff --git a/examples/bpn4.bpn b/examples/bpn4.bpn new file mode 100644 index 0000000..bfb14c9 --- /dev/null +++ b/examples/bpn4.bpn @@ -0,0 +1,39 @@ +// batch petri net + +model test; +length unity= m ; +time unity = s; + +network description +places + place BP (batch) + function (5, 15, 15) // speed, density, length + initial marking {} //length, density, poistion + output arc CTOut + + place CPCap (continuous) + initial marking {225} + output arc CTIn + + place CPIn (continuous) + initial marking {175} + output arc CTIn + + place CPOut (continuous) + initial marking {0} + + +transitions + transition DTIn (discrete) + timing (4) + output arc CPIn (40) + + transition CTIn (batch) + flow (70) + output arc BP + + transition CTOut (batch) + flow (30) + output arc CPCap + output arc CPOut + diff --git a/examples/bpn5.bpn b/examples/bpn5.bpn new file mode 100644 index 0000000..7a8077a --- /dev/null +++ b/examples/bpn5.bpn @@ -0,0 +1,53 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + place CPIn (continuous) + initial marking {150} + output arc BTIn + + place BP1 (batch) + function (4, 15, 12) // speed, density, length + initial marking {} //length, density, poistion + output arc BTMid + + place CPCap1 (continuous) + initial marking {180} + output arc BTIn + + place BP2 (batch) + function (5, 15, 20) // speed, density, length + initial marking {} //length, density, poistion + output arc BTOut + + place CPCap2 (continuous) + initial marking {300} + output arc BTMid + + place CPOut (continuous) + initial marking {} + + +transitions + transition DTIn (discrete) + timing (2) + output arc CPIn (80) + + transition BTIn (batch) + flow (55) + output arc BP1 + + transition BTMid (batch) + flow (80) + output arc BP2 + output arc CPCap1 + + transition BTOut (batch) + flow (30) + output arc CPCap2 + output arc CPOut + diff --git a/examples/bpn6.bpn b/examples/bpn6.bpn new file mode 100644 index 0000000..96b87a3 --- /dev/null +++ b/examples/bpn6.bpn @@ -0,0 +1,21 @@ +// batch petri net + +model test; +length unity= m ; +time unity = s; + +network description +places + place BP (batch) + function (100, 200, 10) // speed, density, length + initial marking {} //length, density, poistion + output arc TOut + +transitions + transition TIn (batch) + flow (15000) + output arc BP + + transition TOut (batch) + flow (10000) + diff --git a/examples/control.bpn b/examples/control.bpn new file mode 100644 index 0000000..950e046 --- /dev/null +++ b/examples/control.bpn @@ -0,0 +1,51 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP3 (batch) + function (1, 2, 4) // speed, density, length + initial marking {} //length, density, poistion + steady marking {(4,1,4)} + output arc T2 + + place BP4 (batch) + function (1, 2, 5) // speed, density, length + initial marking {} //length, density, poistion + steady marking {(3,2,5),(2,1,2)} + output arc T3 + + + place CP1 (continuous) + initial marking {8} + steady marking {4} + output arc T1 + + place CP2 (continuous) + initial marking {8} + steady marking {0} + output arc T2 + +transitions + + transition T1 (batch) + flow (2) + steady flow (1) + output arc BP3 + + transition T2 (batch) + flow (2) + steady flow (1) + output arc BP4 + output arc CP1 + + transition T3 (batch) + flow (1) + steady flow (1) + output arc CP2 + + diff --git a/examples/cpn2p.bpn b/examples/cpn2p.bpn new file mode 100644 index 0000000..e75af7d --- /dev/null +++ b/examples/cpn2p.bpn @@ -0,0 +1,30 @@ +// test continuous petri net + +model continuous_places_transitions; +length unity= m ; +time unity = s; + +network description +places + place PC1 (continuous) + initial marking {0} + output arc TC1 (3) + output arc TC2 (2) + + place PC2 (continuous) + initial marking {100} + output arc TC3 + +transitions + transition TC1 (continuous) + flow (2) + output arc PC2 + + transition TC2 (continuous) + flow (3) + output arc PC2 + + transition TC3 (continuous) + flow (1) + output arc PC1 + diff --git a/examples/cpn5p.bpn b/examples/cpn5p.bpn new file mode 100644 index 0000000..83757e7 --- /dev/null +++ b/examples/cpn5p.bpn @@ -0,0 +1,47 @@ +// test continuous petri net + +model continuous_places_transitions; +length unity= m ; +time unity = s; + +network description +places + place PC1 (continuous) + initial marking {5} + output arc TC1 + + place PC2 (continuous) + initial marking {10} + output arc TC1 + output arc TC2 + + place PC3 (continuous) + initial marking {5} + output arc TC2 + + place PC4 (continuous) + initial marking {0} + output arc TC3 + + place PC5 (continuous) + initial marking {0} + output arc TC4 + +transitions + transition TC1 (continuous) + flow (3) + output arc PC4 + + transition TC2 (continuous) + flow (1) + output arc PC5 + + transition TC3 (continuous) + flow (2) + output arc PC1 + output arc PC2 + + transition TC4 (continuous) + flow (5) + output arc PC2 + output arc PC3 diff --git a/examples/ct.bpn b/examples/ct.bpn new file mode 100644 index 0000000..068e617 --- /dev/null +++ b/examples/ct.bpn @@ -0,0 +1,27 @@ +// test continuous transitions + +model continuous_transitions; +length unity= m ; +time unity = s; + +network description +places + place PC1 (continuous) + initial marking {1} + output arc TC1 + + place PC2 (continuous) + initial marking {1} + output arc TC2 + + +transitions + transition TC1 (continuous) + flow (2) + output arc PC2 + + transition TC2 (continuous) + flow (3) + output arc PC1 + + diff --git a/examples/discretetransition.bpn b/examples/discretetransition.bpn new file mode 100644 index 0000000..4e06277 --- /dev/null +++ b/examples/discretetransition.bpn @@ -0,0 +1,27 @@ +// test discrete transitions + +model discrete_transitions; +length unity= m ; +time unity = s; + +network description +places + place PD1 (discrete) + initial marking {1} + output arc TD1 + + place PD2 (discrete) + initial marking {1} + output arc TD2 + + +transitions + transition TD1 (discrete) + timing (2) + output arc PD2 + + transition TD2 (discrete) + timing (3) + output arc PD1 + + diff --git a/examples/discretetransition.in b/examples/discretetransition.in new file mode 100644 index 0000000..0315137 --- /dev/null +++ b/examples/discretetransition.in @@ -0,0 +1,12 @@ +1 +1 +discretetransition +2 +1 +x +y +10 +0 + + + diff --git a/examples/dpn_1p.bpn b/examples/dpn_1p.bpn new file mode 100644 index 0000000..472023b --- /dev/null +++ b/examples/dpn_1p.bpn @@ -0,0 +1,24 @@ +// test discrete petri net + +model discrete_places_transitions; +length unity= m ; +time unity = s; + +network description +places + place PD1 (discrete) + initial marking {6} + output arc TD1 (3) + output arc TD2 (2) + + +transitions + transition TD1 (discrete) + timing (3) + output arc PD1 + + transition TD2 (discrete) + timing (2) + output arc PD1 + + diff --git a/examples/dpn_3p.bpn b/examples/dpn_3p.bpn new file mode 100644 index 0000000..92d335e --- /dev/null +++ b/examples/dpn_3p.bpn @@ -0,0 +1,35 @@ +// test discrete petri net + +model discrete_places_transitions; +length unity= m ; +time unity = s; + +network description +places + place PD1 (discrete) + initial marking {1} + output arc TD1 + + place PD2 (discrete) + initial marking {0} + output arc TD2 + + place PD3 (discrete) + initial marking {0} + output arc TD3 + + +transitions + transition TD1 (discrete) + timing (0) + output arc PD2 + + transition TD2 (discrete) + timing (0) + output arc PD3 + + transition TD3 (discrete) + timing (3) + output arc PD1 + + diff --git a/examples/dpn_4p.bpn b/examples/dpn_4p.bpn new file mode 100644 index 0000000..927b284 --- /dev/null +++ b/examples/dpn_4p.bpn @@ -0,0 +1,37 @@ +// test discrete petri net + +model discrete_places_transitions; +length unity= m ; +time unity = s; + +network description +places + place PD1 (discrete) + initial marking {2} + output arc TD1 + + place PD2 (discrete) + initial marking {0} + output arc TD2 + + place PD3 (discrete) + initial marking {1} + output arc TD1 + + place PD4 (discrete) + initial marking {1} + output arc TD2 + + +transitions + transition TD1 (discrete) + timing (2) + output arc PD2 + output arc PD3 + + transition TD2 (discrete) + timing (3) + output arc PD1 + output arc PD4 + + diff --git a/examples/fig12.bpn b/examples/fig12.bpn new file mode 100644 index 0000000..4db0df7 --- /dev/null +++ b/examples/fig12.bpn @@ -0,0 +1,82 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {1} + steady marking {0} + output arc T1 + output arc T2 + + place CP2 (continuous) + initial marking {1} + steady marking {2} + output arc T1 + output arc T3 + + place CP3 (continuous) + initial marking {0} + steady marking {0} + output arc T2 + output arc T3 + + place CP4 (continuous) + initial marking {0} + steady marking {0} + output arc T4 + + + place CP5 (continuous) + initial marking {0} + steady marking {0} + output arc T5 + + place CP6 (continuous) + initial marking {0} + steady marking {0} + output arc T6 + +transitions + + transition T1 (continuous) + flow (1) + steady flow (1) + output arc CP4 + + transition T2 (continuous) + flow (1) + steady flow (1) + output arc CP5 + + transition T3 (continuous) + flow (2) + steady flow (1) + output arc CP6 + + transition T4 (continuous) + flow (1) + steady flow (1) + output arc CP1 + output arc CP3 + + + transition T5 (continuous) + flow (1) + steady flow (1) + output arc CP2 + output arc CP3 + + + transition T6 (continuous) + flow (1) + steady flow (1) + output arc CP1 + output arc CP2 + + diff --git a/examples/gbpn1.bpn b/examples/gbpn1.bpn new file mode 100644 index 0000000..a7191fc --- /dev/null +++ b/examples/gbpn1.bpn @@ -0,0 +1,77 @@ +//generalised batch petri net with controllable transfer speed + +model test; +length unity= m ; +time unity = s; + +network description +places + place BP1 (batch) + function (10, 3, 3) // speed, density, length + initial marking {} //length, density, poistion + output arc BT2 + output arc BT3 + + place BP2 (batch) + function (1, 3, 1) // speed, density, length + initial marking {} //length, density, poistion + output arc BT4 + + place BP3 (batch) + function (5, 3, 2) + initial marking {} + output arc BT5 + + place CP4 (continuous) + initial marking {3} + output arc BT1 + + place CP5 (continuous) + initial marking {1} + output arc BT2 + + place CP6 (continuous) + initial marking {3} + output arc BT3 + + + +transitions + transition BT1 (batch) + flow (4) + output arc BP1 + + transition BT2 (batch) + flow (2) + output arc BP2 + output arc CP4 + + transition BT3 (batch) + flow (2) + output arc BP3 + output arc CP4 + + transition BT4 (batch) + flow (4) + output arc CP5 + + transition BT5 (batch) + flow (4) + output arc CP6 + + + + + + + + + + + + + + + + + diff --git a/examples/hpn3p.bpn b/examples/hpn3p.bpn new file mode 100644 index 0000000..e813ec8 --- /dev/null +++ b/examples/hpn3p.bpn @@ -0,0 +1,33 @@ +// test hybrid petri net + +model hybrid_places_transitions; +length unity= m ; +time unity = s; + +network description +places + place PD1 (discrete) + initial marking {2} + output arc TD1 (2) + + place PC2 (continuous) + initial marking {0} + output arc TC2 + + place PC3 (continuous) + initial marking {0} + output arc TD3 (5) + +transitions + transition TD1 (discrete) + timing (3) + output arc PC2 (10) + + transition TC2 (continuous) + flow (1) + output arc PC3 + + transition TD3 (discrete) + timing (2) + output arc PD1 + diff --git a/examples/hpn5p.bpn b/examples/hpn5p.bpn new file mode 100644 index 0000000..9c8e25d --- /dev/null +++ b/examples/hpn5p.bpn @@ -0,0 +1,40 @@ +// test hybrid petri net + +model continuous_places_hybrid_transitions; +length unity= m ; +time unity = s; + +network description +places + place PC1 (continuous) + initial marking {40} + output arc TC1 + + place PC2 (continuous) + initial marking {0} + output arc TD2 (0.00000000001) + + place PC3 (continuous) + initial marking {0} + output arc TC3 + + place PC4 (continuous) + initial marking {0} + + place PC5 (continuous) + initial marking {100} + output arc TC1 + +transitions + transition TC1 (continuous) + flow (50) + output arc PC2 + + transition TD2 (discrete) + timing (2) + output arc PC3 (0.00000000001) + + transition TC3 (continuous) + flow (50) + output arc PC4 + output arc PC5 diff --git a/examples/lego.bpn b/examples/lego.bpn new file mode 100644 index 0000000..9b1c3bd --- /dev/null +++ b/examples/lego.bpn @@ -0,0 +1,70 @@ +// BPN file generated by FreewayLEGO +model lego; +length unity = km; +time unity = h; + +network description +places + place PL_1(triangular) + function (0, 1000, 70, 0) + initial marking {} + output arc TL_1_3 + + place PL_2(triangular) + function (0, 1000, 70, 0) + initial marking {} + output arc TL_2_3 + + place PL0_3(triangular) + function (0, 1000, 130, 0) + initial marking {} + output arc TL_3_I1 + + place PL1_3(triangular) + function (0, 1000, 130, 0) + initial marking {} + output arc TL_3_I2 + + place PL2_3(triangular) + function (0, 1000, 130, 0) + initial marking {} + output arc TL_3_4 + + place PL_4(triangular) + function (0, 1000, 70, 0) + initial marking {} + output arc TL_4_S + + +transitions + transition TL_1_E(batch) + flow (0) + output arc PL_1 + + transition TL_1_3(batch) + flow (0) + output arc PL0_3 + + transition TL_2_E(batch) + flow (0) + output arc PL_2 + + transition TL_2_3(batch) + flow (0) + output arc PL1_3 + + transition TL_3_4(batch) + flow (0) + output arc PL_4 + + transition TL_3_I1(batch) + flow (0) + output arc PL2_3 + + transition TL_3_I2(batch) + flow (0) + output arc PL2_3 + + transition TL_4_S(batch) + flow (0) + diff --git a/examples/optimal.bpn b/examples/optimal.bpn new file mode 100644 index 0000000..8e937ef --- /dev/null +++ b/examples/optimal.bpn @@ -0,0 +1,53 @@ +// batch petri net +// bp2 > 0.5 +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP3 (batch) + function (2, 2, 4) // speed, density, length + initial marking {(4,1,4)} //length, density, poistion + steady marking {(4,1,4)} + output arc T2 + + place BP4 (batch) + function (2, 2, 4) // speed, density, length + initial marking {(3,2,4)} //length, density, poistion + steady marking {(1,2,4),(3,1,3)} + output arc T3 + + + place CP1 (continuous) + initial marking {4} + steady marking {4} + output arc T1 + + place CP2 (continuous) + initial marking {4} + steady marking {5} + output arc T2 + +transitions + + transition T1 (batch) + flow (4) + steady flow (2) + output arc BP3 + + transition T2 (batch) + flow (2) + steady flow (2) + output arc BP4 + output arc CP1 + + transition T3 (batch) + flow (2) + steady flow (2) + output arc CP2 + + + + diff --git a/examples/periodic1.bpn b/examples/periodic1.bpn new file mode 100644 index 0000000..b85f149 --- /dev/null +++ b/examples/periodic1.bpn @@ -0,0 +1,51 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP3 (batch) + function (1, 2, 4) // speed, density, length + initial marking {} //length, density, poistion + steady marking {(4,1,4)} + output arc T2 + + place BP4 (batch) + function (1, 2, 5) // speed, density, length + initial marking {} //length, density, poistion + steady marking {(3,2,5),(2,1,2)} + output arc T3 + + + place CP1 (continuous) + initial marking {3} + steady marking {4} + output arc T1 + + place CP2 (continuous) + initial marking {3} + steady marking {0} + output arc T2 + +transitions + + transition T1 (batch) + flow (2) + steady flow (1) + output arc BP3 + + transition T2 (batch) + flow (2) + steady flow (1) + output arc BP4 + output arc CP1 + + transition T3 (batch) + flow (1) + steady flow (1) + output arc CP2 + + diff --git a/examples/petrinets.bpn b/examples/petrinets.bpn new file mode 100644 index 0000000..b779b59 --- /dev/null +++ b/examples/petrinets.bpn @@ -0,0 +1,52 @@ +// double "/" for comments +model example; +length unity=km; +time unity=h; + + +network description + places + place DPlace (discrete) + initial marking {2} // integer value + output arc DTransition // 2 is the weight of the arc + + place CPlace (continuous) + initial marking {2.3} // real value + output arc CTransition // if no specified weight is 1 + + place BPlace (batch) + function (110, 200, 10) // speed, max density, and length + initial marking {(1.2, 150, 2)} + // list of initial batches {(length, density, position), ..} + output arc BTransition + + transitions + transition DTransition (discrete) + timing (4) // real value + output arc CPlace + + transition CTransition (continuous) + flow (2.0) // real value + output arc BPlace + + transition BTransition (batch) + flow (200.0) // real value + + + + + + + + + + + + + + + + + + + diff --git a/examples/pn_discrets.bpn b/examples/pn_discrets.bpn new file mode 100644 index 0000000..6920813 --- /dev/null +++ b/examples/pn_discrets.bpn @@ -0,0 +1,27 @@ +// test discrete petri net + +model discrete_places_transitions; +length unity= m ; +time unity = s; + +network description +places + place PD1 (discrete) + initial marking {1} + output arc TD1 + + place PD2 (discrete) + initial marking {1} + output arc TD2 + + +transitions + transition TD1 (discrete) + timing (2) + output arc PD2 + + transition TD2 (discrete) + timing (3) + output arc PD1 + + diff --git a/examples/pureCPN.bpn b/examples/pureCPN.bpn new file mode 100644 index 0000000..b8116dd --- /dev/null +++ b/examples/pureCPN.bpn @@ -0,0 +1,47 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {0.5} + steady marking {1} + output arc T1 + + place CP2 (continuous) + initial marking {0} + steady marking {0.1} + output arc T2 + output arc T3 + + place CP3 (continuous) + initial marking {10} + steady marking {9.4} + output arc T3 + +transitions + + transition T1 (continuous) + flow (1) + steady flow (1) + output arc CP2 + + transition T2 (continuous) + flow (1) + steady flow (1) + output arc CP3 + + transition T3 (continuous) + flow (1) + steady flow (1) + output arc CP1 + output arc CP2 + + + + diff --git a/examples/pureCPN2.bpn b/examples/pureCPN2.bpn new file mode 100644 index 0000000..bb2c7af --- /dev/null +++ b/examples/pureCPN2.bpn @@ -0,0 +1,47 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {1} + steady marking {0.5} + output arc T1 + + place CP2 (continuous) + initial marking {0.3} + steady marking {0.5} + output arc T2 + output arc T3 + + place CP3 (continuous) + initial marking {10} + steady marking {10.3} + output arc T2 + +transitions + + transition T1 (continuous) + flow (1) + steady flow (1) + output arc CP2 + + transition T2 (continuous) + flow (1) + steady flow (1) + output arc CP1 + output arc CP2 + + transition T3 (continuous) + flow (1) + steady flow (1) + output arc CP3 + + + + diff --git a/examples/pureCPN21.bpn b/examples/pureCPN21.bpn new file mode 100644 index 0000000..c25607e --- /dev/null +++ b/examples/pureCPN21.bpn @@ -0,0 +1,52 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {3} + steady marking {5.5} + output arc T1 (2) + + place CP2 (continuous) + initial marking {1} + steady marking {0.75} + output arc T2 + + place CP3 (continuous) + initial marking {3} + steady marking {0.75} + output arc T3 + + place CP4 (continuous) + initial marking {3} + steady marking {1.5} + output arc T1 (2) + output arc T2 + + +transitions + + transition T1 (continuous) + flow (1) + steady flow (1) + output arc CP2 + output arc CP3 + + transition T2 (continuous) + flow (1) + steady flow (1) + output arc CP1 + + transition T3 (continuous) + flow (1) + steady flow (1) + output arc CP1 + output arc CP4 (3) + + diff --git a/examples/pureCPN3.bpn b/examples/pureCPN3.bpn new file mode 100644 index 0000000..7e5f7cf --- /dev/null +++ b/examples/pureCPN3.bpn @@ -0,0 +1,45 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {0.5} + steady marking {1} + output arc T1 + + place CP2 (continuous) + initial marking {0.3} + steady marking {0.5} + output arc T2 + output arc T3 (2) + + place CP3 (continuous) + initial marking {10} + steady marking {9.3} + output arc T3 (2) + +transitions + + transition T1 (continuous) + flow (1) + steady flow (1) + output arc CP2 + + transition T2 (continuous) + flow (2) + steady flow (2) + output arc CP3 + + transition T3 (continuous) + flow (1) + steady flow (1) + output arc CP1 + output arc CP2 (3) + + diff --git a/examples/pureCPN31.bpn b/examples/pureCPN31.bpn new file mode 100644 index 0000000..2c29822 --- /dev/null +++ b/examples/pureCPN31.bpn @@ -0,0 +1,41 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {4} + steady marking {2.5} + output arc T1 + + place CP2 (continuous) + initial marking {0} + steady marking {1.5} + output arc T2 + + place CP3 (continuous) + initial marking {1} + steady marking {2.5} + output arc T1 + output arc T2 (2) + +transitions + + transition T1 (continuous) + flow (2.5) + steady flow (2.5) + output arc CP2 + output arc CP3 (2) + + transition T2 (continuous) + flow (2.5) + steady flow (2.5) + output arc CP1 + output arc CP3 + + diff --git a/examples/pureCPN4.bpn b/examples/pureCPN4.bpn new file mode 100644 index 0000000..8c3f442 --- /dev/null +++ b/examples/pureCPN4.bpn @@ -0,0 +1,45 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {0.5} + steady marking {1} + output arc T1 + + place CP2 (continuous) + initial marking {0.3} + steady marking {0.5} + output arc T2 + output arc T3 (2) + + place CP3 (continuous) + initial marking {10} + steady marking {9.3} + output arc T3 + +transitions + + transition T1 (continuous) + flow (1) + steady flow (1) + output arc CP2 + + transition T2 (continuous) + flow (2) + steady flow (2) + output arc CP3 + + transition T3 (continuous) + flow (1) + steady flow (1) + output arc CP1 + output arc CP2 (3) + + diff --git a/examples/pureCPN5.bpn b/examples/pureCPN5.bpn new file mode 100644 index 0000000..7e5f7cf --- /dev/null +++ b/examples/pureCPN5.bpn @@ -0,0 +1,45 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {0.5} + steady marking {1} + output arc T1 + + place CP2 (continuous) + initial marking {0.3} + steady marking {0.5} + output arc T2 + output arc T3 (2) + + place CP3 (continuous) + initial marking {10} + steady marking {9.3} + output arc T3 (2) + +transitions + + transition T1 (continuous) + flow (1) + steady flow (1) + output arc CP2 + + transition T2 (continuous) + flow (2) + steady flow (2) + output arc CP3 + + transition T3 (continuous) + flow (1) + steady flow (1) + output arc CP1 + output arc CP2 (3) + + diff --git a/examples/pureCPN6.bpn b/examples/pureCPN6.bpn new file mode 100644 index 0000000..a00ca08 --- /dev/null +++ b/examples/pureCPN6.bpn @@ -0,0 +1,45 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {0.5} + steady marking {1} + output arc T1 + + place CP2 (continuous) + initial marking {0.3} + steady marking {0.5} + output arc T2 + output arc T3 (2) + + place CP3 (continuous) + initial marking {10} + steady marking {9.3} + output arc T3 + +transitions + + transition T1 (continuous) + flow (3) + steady flow (1) + output arc CP2 + + transition T2 (continuous) + flow (1) + steady flow (1) + output arc CP3 + + transition T3 (continuous) + flow (1) + steady flow (1) + output arc CP1 (3) + output arc CP2 + + diff --git a/examples/pureCPN7.bpn b/examples/pureCPN7.bpn new file mode 100644 index 0000000..b8ecc80 --- /dev/null +++ b/examples/pureCPN7.bpn @@ -0,0 +1,45 @@ +// pure continuous petri net with constant speed. + + +model test; +length unity= m ; +time unity = m; + +network description +places + + place CP1 (continuous) + initial marking {0.1} + steady marking {0.3} + output arc T1 + + place CP2 (continuous) + initial marking {0.5} + steady marking {1} + output arc T2 + output arc T3 (3) + + place CP3 (continuous) + initial marking {10} + steady marking {9.3} + output arc T3 + +transitions + + transition T1 (continuous) + flow (2) + steady flow (2) + output arc CP2 + + transition T2 (continuous) + flow (1) + steady flow (1) + output arc CP3 + + transition T3 (continuous) + flow (1) + steady flow (1) + output arc CP1 (2) + output arc CP2 (2) + + diff --git a/examples/tbpn.bpn b/examples/tbpn.bpn new file mode 100644 index 0000000..6db13af --- /dev/null +++ b/examples/tbpn.bpn @@ -0,0 +1,22 @@ +// Trinagular batch petri net + +model test_tbpn; +length unity= km ; +time unity = h; + +network description +places + place BP1 (triangular) + function (100, 200, 10, 5000) // speed, density, length + initial marking {} //length, density, poistion + output arc BTOut + + +transitions + transition BTIn (batch) + flow (1000) + output arc BP1 + + transition BTOut (batch) + flow (100) + diff --git a/examples/tbpn2.bpn b/examples/tbpn2.bpn new file mode 100644 index 0000000..b8c8864 --- /dev/null +++ b/examples/tbpn2.bpn @@ -0,0 +1,41 @@ +// Trinagular batch petri net + +model test_tbpn; +length unity= km ; +time unity = h; + +network description +places + place DP1 (discrete) + initial marking {2} + output arc DTIn + + place CP2 (continuous) + initial marking {0} + output arc CTMid + + place BP3 (triangular) + function (50, 200, 100, 2000) // speed, density, length + initial marking {} //length, density, poistion + output arc BTOut + + +transitions + transition DTIn (discrete) + timing (1) + output arc CP2 (400) + + transition CTMid (continuous) + flow (1000) + output arc BP3 + + transition BTOut (batch) + flow (100) + +controlled events // les evenements controlles pourrons aussi etre lu a partir d un fichier externe + ev1 = (flow, BTOut, 1000, 3.5); +// ev2 = (speed, PT, 120, 0.002); + +time inspection // affiche l information d une place(caracteristiques+lots)/transition(flux) a l instant <time> + res1 = @ 1.5 ? BP3; + res2 = # 1.0 * places diff --git a/examples/tbpn3.bpn b/examples/tbpn3.bpn new file mode 100644 index 0000000..7b81d52 --- /dev/null +++ b/examples/tbpn3.bpn @@ -0,0 +1,35 @@ +// Trinagular batch petri net + +model test_tbpn; +length unity= km ; +time unity = h; + +network description +places + place CP1 (continuous) + initial marking {10000} + output arc CTIn + + place BP2 (triangular) + function (50, 200, 100, 2000) // speed, density, length + initial marking {} //length, density, poistion + output arc BTOut + + +transitions + transition CTIn (batch) + flow (1000) + output arc BP2 + + transition BTOut (batch) + flow (1000) + +controlled events // les evenements controlles pourrons aussi etre lu a partir d un fichier externe + ev1 = (flow, BTOut, 100, 5); + ev2 = (flow, BTOut, 100, 4); + +// ev2 = (speed, PT, 120, 0.002); + +time inspection // affiche l information d une place(caracteristiques+lots)/transition(flux) a l instant <time> + res1 = @ 1.5 ? BP2; + res2 = # 1.0 * places diff --git a/examples/tbpn4.bpn b/examples/tbpn4.bpn new file mode 100644 index 0000000..3c0b69e --- /dev/null +++ b/examples/tbpn4.bpn @@ -0,0 +1,25 @@ +// Trinagular batch petri net + +model test_tbpn; +length unity= km ; +time unity = h; + +network description +places + place BP2 (triangular) + function (50, 200, 100, 2000) // speed, density, length + initial marking {(5.20833333333, 192, 100, 0.5208333333333334)} //length, density, poistion, speed + output arc BTOut + + +transitions + transition BTOut (batch) + flow (1000) + +controlled events // les evenements controlles pourrons aussi etre lu a partir d un fichier externe + ev1 = (flow, BTOut, 1000, 0.003); + ev2 = (speed, BP2, 30, 0.002); + +time inspection // affiche l information d une place(caracteristiques+lots)/transition(flux) a l instant <time> + res1 = @ 1.5 ? BP2; + res2 = # 1.0 * places diff --git a/examples/test.bpn b/examples/test.bpn new file mode 100644 index 0000000..46a0401 --- /dev/null +++ b/examples/test.bpn @@ -0,0 +1,67 @@ +// comments + +model test; +length unity= m ; +time unity = s; + +network description +places + place PD (discrete) + initial marking {1} + steady marking {1} + output arc T1 + output arc T2 (2) + + place PC (continuous) + initial marking {2.5} + steady marking {2.5} + + output arc t3 (1) + output arc t4 + + place PC2 (continuous) + initial marking {2.5} + output arc t3 (1) + output arc t4 + + place PB (batch) + function (10,120, 200 ) + initial marking { (1, 1.2, 100) } + output arc t3 +// output arc t6 (3) + + place PT (triangular) + function ( 120, 250, 10.4, 4000) + initial marking { (2.3, 1.0,50, 200) , + (3, 10, 120, 300) } + output arc t4 (3.2) + +transitions + transition T1 (discrete) + timing (5.1) + output arc PD + output arc PC (2) + + transition T2 (continuous) + flow (300.5) + output arc PC2 + output arc PB + + transition t3 (batch) + flow (4000) + output arc PT + + transition t4 (batch) + flow (4000) + output arc PT + + +controlled events // les evenements controlles pourrons aussi etre lu a partir d un fichier externe + ev1 = (flow, T1, 4000, 0.001); + ev2 = (speed, PT, 120, 0.002); + +time inspection // affiche l information d une place(caracteristiques+lots)/transition(flux) a l instant <time> + res1 = @ 1.001 ? pt; + res2 = # 1.02 * places + + diff --git a/examples/test1.bpn b/examples/test1.bpn new file mode 100644 index 0000000..f84c824 --- /dev/null +++ b/examples/test1.bpn @@ -0,0 +1,32 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + + place BP2 (batch) + function (10, 3, 3) // speed, density, length + initial marking {} //length, density, poistion + steady marking {(3,0.4,3)} + output arc T2 + + place CP1 (continuous) + initial marking {3} + steady marking {1.8} + output arc T1 + +transitions + + transition T1 (batch) + flow (4) + steady flow (4) + output arc BP2 + + transition T2 (batch) + flow (4) + steady flow (4) + output arc CP1 + diff --git a/examples/test2.bpn b/examples/test2.bpn new file mode 100644 index 0000000..213c049 --- /dev/null +++ b/examples/test2.bpn @@ -0,0 +1,38 @@ +// batch petri net + +model test; +length unity= m ; +time unity = m; + +network description +places + + + + place BP2 (batch) + function (1, 2, 5) // speed, density, length + initial marking {} //length, density, poistion + steady marking {(3,2,5),(2,1,2)} + output arc T2 (0.5) + + + place CP1 (continuous) + initial marking {9} + steady marking {1} + output arc T1 (2) + + + +transitions + + transition T1 (batch) + flow (1) + steady flow (1) + output arc BP2 + + transition T2 (batch) + flow (1) + steady flow (1) + output arc CP1 + + diff --git a/examples/test_steady.bpn b/examples/test_steady.bpn new file mode 100644 index 0000000..b8dbd7d --- /dev/null +++ b/examples/test_steady.bpn @@ -0,0 +1,76 @@ +// comments + +model test; +length unity= m ; +time unity = s; + +network description +places + place PD (discrete) + initial marking {1} + steady marking {1} + output arc T1 + output arc T2 (2) + + place PC (continuous) + initial marking {2.5} + steady marking {2.5} + output arc t3 (1) + output arc t4 + + place PC2 (continuous) + initial marking {2.5} + output arc t3 (1) + output arc t4 + + place PB (batch) + function (10,120, 200 ) + initial marking { (1, 1.2, 100) } + steady marking { (1, 1, 100), (9, 2, 200) } + + output arc t3 +// output arc t6 (3) + + place PT (triangular) + function ( 120, 250, 10.4, 4000) + initial marking { (2.3, 1.0,50, 200) , + (3, 10, 120, 300) } + steady marking { (2.3, 1.0,50, 200) , + (4, 10, 120, 300) } + output arc t4 (3.2) + +transitions + transition T1 (discrete) + timing (5.1) + steady timing (4.0) + output arc PD + output arc PC (2) + + transition T2 (continuous) + flow (300.5) + steady flow (300.5) + + output arc PC2 + output arc PB + + transition t3 (batch) + flow (4000) + steady flow (300.5) + + output arc PT + + transition t4 (batch) + flow (4000) + steady flow (3000) + output arc PT + + +controlled events // les evenements controlles pourrons aussi etre lu a partir d un fichier externe + ev1 = (flow, T2, 4000, 0.001); + ev2 = (speed, PT, 120, 0.002); + +time inspection // affiche l information d une place(caracteristiques+lots)/transition(flux) a l instant <time> + res1 = @ 1.001 ? PT; + res2 = # 1.02 * places + + diff --git a/simuleau.cbp b/simuleau.cbp new file mode 100644 index 0000000..d6b04ce --- /dev/null +++ b/simuleau.cbp @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="simuleau" /> + <Option pch_mode="2" /> + <Option compiler="gcc" /> + <Build> + <Target title="Debug"> + <Option output="bin/Debug/simuleau" prefix_auto="1" extension_auto="1" /> + <Option working_dir="bin/Debug" /> + <Option object_output="obj/Debug/" /> + <Option type="1" /> + <Option compiler="gcc" /> + <Compiler> + <Add option="-w" /> + <Add option="-pg" /> + <Add option="-g" /> + <Add option="-Wunused-result" /> + <Add option="-O0" /> + <Add option="-D_SIMULEAU_DEBUG_" /> + <Add directory="src" /> + <Add directory="src/bpn" /> + <Add directory="src/interf" /> + <Add directory="src/simul" /> + </Compiler> + <Linker> + <Add option="-pg" /> + <Add option="-static-libstdc++" /> + <Add option="-static-libgcc" /> + <Add library="glpk" /> + <Add library="libglpk" /> + <Add directory="/usr/local/lib" /> + <Add directory="/usr/local/include" /> + <Add directory="/usr/include" /> + <Add directory="/usr/lib/x86_64-linux-gnu/" /> + </Linker> + <ExtraCommands> + <Add before="lex -o src/interf/y.tab.cpp src/interf/tokens.l" /> + <Add before="yacc -tdv -o src/interf/y.tab.cpp src/interf/glc.y" /> + <Mode after="always" /> + </ExtraCommands> + </Target> + <Target title="Release"> + <Option output="bin/Release/simuleau" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Release/" /> + <Option type="1" /> + <Option compiler="gcc" /> + <Compiler> + <Add option="-O2" /> + <Add directory="src/bpn" /> + <Add directory="src/simul" /> + <Add directory="src" /> + <Add directory="src/interf" /> + </Compiler> + <Linker> + <Add option="-s" /> + <Add library="glpk" /> + </Linker> + <ExtraCommands> + <Add before="yacc -tdv -o src/interf/y.tab.cpp src/interf/glc.y" /> + </ExtraCommands> + </Target> + </Build> + <Compiler> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-fexceptions" /> + <Add option="-fpermissive" /> + <Add directory="src" /> + </Compiler> + <Linker> + <Add library="glpk" /> + <Add library="dl" /> + </Linker> + <Unit filename="src/bpn/arc.cpp" /> + <Unit filename="src/bpn/arc.h" /> + <Unit filename="src/bpn/batch.cpp" /> + <Unit filename="src/bpn/batch.h" /> + <Unit filename="src/bpn/batchplace.cpp" /> + <Unit filename="src/bpn/batchtransition.cpp" /> + <Unit filename="src/bpn/bpn.cpp" /> + <Unit filename="src/bpn/bpn.h" /> + <Unit filename="src/bpn/continuousplace.cpp" /> + <Unit filename="src/bpn/continuoustransition.cpp" /> + <Unit filename="src/bpn/controllablebatch.cpp" /> + <Unit filename="src/bpn/discreteplace.cpp" /> + <Unit filename="src/bpn/discretetransition.cpp" /> + <Unit filename="src/bpn/firingquantity.cpp" /> + <Unit filename="src/bpn/firingquantity.h" /> + <Unit filename="src/bpn/flow.cpp" /> + <Unit filename="src/bpn/flow.h" /> + <Unit filename="src/bpn/node.cpp" /> + <Unit filename="src/bpn/node.h" /> + <Unit filename="src/bpn/place.cpp" /> + <Unit filename="src/bpn/place.h" /> + <Unit filename="src/bpn/transition.cpp" /> + <Unit filename="src/bpn/transition.h" /> + <Unit filename="src/bpn/triangularbatchplace.cpp" /> + <Unit filename="src/interf/bpnfile.h" /> + <Unit filename="src/interf/error_msgs.h" /> + <Unit filename="src/interf/interf.cpp" /> + <Unit filename="src/interf/interf.h" /> + <Unit filename="src/interf/lex.yy.cpp"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/interf/prf.cpp" /> + <Unit filename="src/interf/prf.h" /> + <Unit filename="src/interf/timer.cpp" /> + <Unit filename="src/interf/timer.h" /> + <Unit filename="src/interf/y.tab.cpp"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/interf/y.tab.h" /> + <Unit filename="src/interf/y.tab.hpp" /> + <Unit filename="src/simul/breakpoint.cpp" /> + <Unit filename="src/simul/breakpoint.h" /> + <Unit filename="src/simul/event.cpp" /> + <Unit filename="src/simul/event.h" /> + <Unit filename="src/simul/schedule.cpp" /> + <Unit filename="src/simul/schedule.h" /> + <Unit filename="src/simul/simtime.cpp" /> + <Unit filename="src/simul/simtime.h" /> + <Unit filename="src/simul/simulate.cpp" /> + <Unit filename="src/simul/simulate.h" /> + <Unit filename="src/simuleau.cpp" /> + <Unit filename="src/simuleau.h" /> + <Extensions /> + </Project> +</CodeBlocks_project_file> diff --git a/simuleau.layout b/simuleau.layout new file mode 100644 index 0000000..6318617 --- /dev/null +++ b/simuleau.layout @@ -0,0 +1,230 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_layout_file> + <FileVersion major="1" minor="0" /> + <ActiveTarget name="Debug" /> + <File name="src/bpn/arc.cpp" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1012" topLine="0" /> + </Cursor> + </File> + <File name="src/interf/interf.h" open="0" top="0" tabpos="19" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="2344" topLine="27" /> + </Cursor> + </File> + <File name="src/bpn/triangularbatchplace.cpp" open="0" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="26249" topLine="763" /> + </Cursor> + </File> + <File name="src/simul/event.h" open="0" top="0" tabpos="15" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1583" topLine="47" /> + </Cursor> + </File> + <File name="src/bpn/firingquantity.h" open="0" top="0" tabpos="17" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1151" topLine="0" /> + </Cursor> + </File> + <File name="src/bpn/continuousplace.cpp" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="14296" topLine="165" /> + </Cursor> + </File> + <File name="src/simul/simulate.cpp" open="1" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="5815" topLine="328" /> + </Cursor> + </File> + <File name="src/simul/event.cpp" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="4108" topLine="201" /> + </Cursor> + </File> + <File name="src/bpn/continuoustransition.cpp" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="5687" topLine="255" /> + </Cursor> + </File> + <File name="src/bpn/arc.h" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="827" topLine="1" /> + </Cursor> + </File> + <File name="src/bpn/batch.cpp" open="0" top="0" tabpos="14" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="3680" topLine="87" /> + </Cursor> + </File> + <File name="src/simuleau.h" open="1" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="2051" topLine="12" /> + </Cursor> + </File> + <File name="src/bpn/flow.cpp" open="0" top="0" tabpos="12" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="4499" topLine="34" /> + </Cursor> + </File> + <File name="src/bpn/batchplace.cpp" open="0" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="-1" zoom_2="0"> + <Cursor> + <Cursor1 position="20802" topLine="645" /> + </Cursor> + </File> + <File name="src/simul/simtime.cpp" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="2749" topLine="71" /> + </Cursor> + </File> + <File name="src/interf/prf.h" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1362" topLine="0" /> + </Cursor> + </File> + <File name="src/bpn/place.h" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="3812" topLine="183" /> + </Cursor> + </File> + <File name="src/simul/breakpoint.cpp" open="0" top="0" tabpos="12" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="5659" topLine="142" /> + </Cursor> + </File> + <File name="src/bpn/transition.h" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="2798" topLine="123" /> + </Cursor> + </File> + <File name="src/bpn/discreteplace.cpp" open="0" top="0" tabpos="16" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="6047" topLine="139" /> + </Cursor> + </File> + <File name="src/simul/simulate.h" open="0" top="0" tabpos="12" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1402" topLine="0" /> + </Cursor> + </File> + <File name="src/simul/breakpoint.h" open="0" top="0" tabpos="16" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="2086" topLine="15" /> + </Cursor> + </File> + <File name="src/bpn/node.cpp" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="6150" topLine="171" /> + </Cursor> + </File> + <File name="src/simul/schedule.cpp" open="0" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="25197" topLine="710" /> + </Cursor> + </File> + <File name="src/interf/lex.yy.cpp" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="513" /> + </Cursor> + </File> + <File name="src/bpn/flow.h" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1549" topLine="20" /> + </Cursor> + </File> + <File name="src/bpn/firingquantity.cpp" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="2746" topLine="36" /> + </Cursor> + </File> + <File name="src/bpn/bpn.h" open="0" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="6212" topLine="105" /> + </Cursor> + </File> + <File name="src/interf/error_msgs.h" open="0" top="0" tabpos="15" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="4237" topLine="64" /> + </Cursor> + </File> + <File name="src/bpn/place.cpp" open="0" top="0" tabpos="16" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="2431" topLine="51" /> + </Cursor> + </File> + <File name="src/bpn/controllablebatch.cpp" open="0" top="0" tabpos="12" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="4136" topLine="57" /> + </Cursor> + </File> + <File name="src/interf/interf.cpp" open="1" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="22430" topLine="510" /> + </Cursor> + </File> + <File name="src/simul/simtime.h" open="0" top="0" tabpos="13" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1485" topLine="2" /> + </Cursor> + </File> + <File name="src/interf/y.tab.cpp" open="0" top="0" tabpos="21" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="6548" topLine="124" /> + </Cursor> + </File> + <File name="src/interf/bpnfile.h" open="0" top="0" tabpos="14" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="39" topLine="0" /> + </Cursor> + </File> + <File name="src/simuleau.cpp" open="1" top="1" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="5708" topLine="102" /> + </Cursor> + </File> + <File name="src/simul/schedule.h" open="0" top="0" tabpos="14" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="2038" topLine="46" /> + </Cursor> + </File> + <File name="src/interf/prf.cpp" open="0" top="0" tabpos="12" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="4727" topLine="181" /> + </Cursor> + </File> + <File name="src/bpn/batchtransition.cpp" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="8375" topLine="200" /> + </Cursor> + </File> + <File name="src/bpn/batch.h" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="3511" topLine="76" /> + </Cursor> + </File> + <File name="src/bpn/node.h" open="0" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1882" topLine="22" /> + </Cursor> + </File> + <File name="src/bpn/bpn.cpp" open="0" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="24657" topLine="671" /> + </Cursor> + </File> + <File name="src/bpn/transition.cpp" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="5446" topLine="334" /> + </Cursor> + </File> + <File name="src/interf/timer.cpp" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1364" topLine="45" /> + </Cursor> + </File> + <File name="src/bpn/discretetransition.cpp" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="2748" topLine="46" /> + </Cursor> + </File> +</CodeBlocks_layout_file> diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9cda2562d7da1a9fc4dedf9de3925e9687f8ea4c GIT binary patch literal 6148 zcmZQzU|@7AO)+F(5MW?n;9!8zOq>i@0Z1N%F(jFwA}k>DKxPydB<18MF)%QkOe%oN zjZ%X<1VC}e%#g%Tz>t?zjvRkEnZ+dr2G<#xm|0la*f}`3IJkJZVuLgC%Y#c2OG=BK z5{sfiynw`#j3g*KBtJg~&Q44U%S<hg7Z7pI&nrpH%u6i-DG$y}Nli*DiV4rmOUW;H z$}i1JDF&MZmEhpu<lu}Kkf^RUGB(puFt)U))lsN6H#g8xFflf(t>xqpS2eWtOvtUQ zs;;T6n+XYBMn(wDzz?Ni)GP)D2B`N^ij#Aa^7C^*Qc$6?;G(>o{JeBX`ek5cC}zlH z$Ym&H$bl(_nG4c1ibq3WGz3ONVAzBJv~c6#9yUH2^~h)ljD`TULI6}gC_vjr4p6!Q zLW86j7#SGAT>wS~22e8+Y%L?G9{^DU(h5=o(h8zMS{WEYEU-LSD+41`D<ilY!oa`? z?vj9LuyzJU2C#MpMh38U23Sjv5u%-e5o$9dw1>h7>d}DAhiGSDglGr5ZIl=dfzc2^ zga9*yDFCYfT^Sf~_5UHNM#<3-7!84883K$fF2OENph^>m_ds<ms6I`A%7bcuP<6}* ss;3cR;HsDjGN32{6$VxJAgv%8Top4iKx*>Qh5#&tM(NQIpnnJe0FozJ@Bjb+ literal 0 HcmV?d00001 diff --git a/src/bpn/arc.cpp b/src/bpn/arc.cpp new file mode 100644 index 0000000..80bd388 --- /dev/null +++ b/src/bpn/arc.cpp @@ -0,0 +1,22 @@ +//====================================================================================// +// // +// Arc class // +// // +//====================================================================================// +// This File: arc.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +Arc::Arc() +{ + //ctor +} + +Arc::~Arc() +{ + //dtor +} diff --git a/src/bpn/arc.h b/src/bpn/arc.h new file mode 100644 index 0000000..98fbc1f --- /dev/null +++ b/src/bpn/arc.h @@ -0,0 +1,29 @@ +//====================================================================================// +// // +// Arc class // +// // +//====================================================================================// +// This File: arc.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef ARC_H +#define ARC_H + +class Arc +{ + public: + Arc(); + virtual ~Arc(); + + protected: + double weight; // weight associated to this arc + Node *input; // pointer to the input node + Node *output; // pointer to the input node + + private: +}; + +#endif // ARC_H diff --git a/src/bpn/batch.cpp b/src/bpn/batch.cpp new file mode 100644 index 0000000..1628cbc --- /dev/null +++ b/src/bpn/batch.cpp @@ -0,0 +1,260 @@ +//====================================================================================// +// // +// Batch class // +// // +//====================================================================================// +// This File: batch.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 28/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 28/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Batch class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Batch::Batch() +{ + strcpy(name,""); + length = 0.0; + density = 0.0; + position = 0.0; + outputflow = 0.0; +} + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Batch::Batch(char *_name) +{ + strcpy(name,"_name"); + length = 0.0; + density = 0.0; + position = 0.0; + outputflow = 0.0; +} + +//------------------------------------------------------------------------------ +// Initialized constructor +//------------------------------------------------------------------------------ +Batch::Batch(double _length, double _density, double _position) +{ + length = _length; + density = _density; + position = _position; + outputflow = 0.0; +} + +//------------------------------------------------------------------------------ +// Initialized constructor +//------------------------------------------------------------------------------ +Batch::Batch(double _inputflow, double _speed) +{ + length = 0.0; + density = _inputflow/_speed; + position = 0.0; + outputflow = 0.0; +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Batch::~Batch() +{ + //dtor +} + +//------------------------------------------------------------------------------ +// It returns the batch name +//------------------------------------------------------------------------------ +char* Batch::GetName() +{ + return (name); +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void Batch::Copy(const Batch &_batch) +{ + strcpy(name, _batch.name); + length = _batch.length; + density = _batch.density; + position = _batch.position; + outputflow = _batch.outputflow; +} + +//------------------------------------------------------------------------------ +// IsEqual +//------------------------------------------------------------------------------ +int Batch::IsEqual(const Batch &_batch) +{ + if (abs(length - _batch.length) > PRF::prf.Min_Err()) + return 0; + if (abs(density - _batch.density) > PRF::prf.Min_Err()) + return 0; + if (abs(position - _batch.position) > PRF::prf.Min_Err()) + return 0; + return 1; +} + +//------------------------------------------------------------------------------ +// It sets a new density +//------------------------------------------------------------------------------ +void Batch::SetDensity(double _density) +{ + density = _density; +} + +//------------------------------------------------------------------------------ +// It sets a new length +//------------------------------------------------------------------------------ +void Batch::SetLength(double _length) +{ + length = _length; +} + +//------------------------------------------------------------------------------ +// It sets a new position +//------------------------------------------------------------------------------ +void Batch::SetPosition(double _position) +{ + position = _position; +} + +//------------------------------------------------------------------------------ +// It moves the position +//------------------------------------------------------------------------------ +void Batch::MovePosition(double _length) +{ + position += _length; +} + +//------------------------------------------------------------------------------ +// It returns the density +//------------------------------------------------------------------------------ +double Batch::GetDensity() +{ + return (density); +} + +//------------------------------------------------------------------------------ +// It returns the length +//------------------------------------------------------------------------------ +double Batch::GetLength() +{ + return (length); +} + +//------------------------------------------------------------------------------ +// It returns the position +//------------------------------------------------------------------------------ +double Batch::GetPosition() +{ + return (position); +} + +//------------------------------------------------------------------------------ +// It computes and returns the output flow of a batch +//------------------------------------------------------------------------------ +double Batch::GetOutputFlow(double _speed) +{ + outputflow = density * _speed; + return (outputflow); +} + +//------------------------------------------------------------------------------ +// It applies the free behaviour at this batch +//------------------------------------------------------------------------------ +void Batch::EvolveInFreeBehaviour(Simtime *_stime, BatchPlace *bp) +{ + double newposition; + + newposition = position + (bp->GetInstantaneousSpeed() * _stime->StepTime()); + if ((position == 0.0) && (length == 0.0)){ //new batch, input in free behaviour + length = newposition; + position = newposition; + } + else{ + if ((bp->GetLength() - position) < PRF::prf.Min_Err()){ + length -= (bp->GetInstantaneousSpeed() * _stime->StepTime()); + position = bp->GetLength(); + } + else{ + position = newposition; + } + } +} + +//------------------------------------------------------------------------------ +// It applies the accumulated behaviour to the outpout batch +//------------------------------------------------------------------------------ +void Batch::EvolveInAccumulatedOuputBehaviour(Simtime *_stime, BatchPlace *bp, double _flow) +{ + length = length - (_stime->StepTime() * _flow / bp->GetDensity()); +} + +//------------------------------------------------------------------------------ +// It applies the free to accumulated behaviour in the accumulated batch +//------------------------------------------------------------------------------ +void Batch::EvolveInFreeToAccumulatedBehaviourAccBatch(Simtime *_stime, BatchPlace *bp, double _flow) +{ + length = (((bp->GetInstantaneousSpeed() * density - _flow) / ( bp->GetDensity() - density)) * _stime->StepTime()); + density = bp->GetDensity(); +} + + +//------------------------------------------------------------------------------ +// It applies the free to accumulated behaviour in the free batch +//------------------------------------------------------------------------------ +void Batch::EvolveInFreeToAccumulatedBehaviourFreeBatch(Simtime *_stime, BatchPlace *bp, double outputbatchlength, double _flow) +{ + length = length + ((_flow - bp->GetInstantaneousSpeed() * bp->GetDensity()) / (bp->GetDensity() - density)) * _stime->StepTime() ; + position = bp->GetLength() - outputbatchlength; +} + + + +//------------------------------------------------------------------------------ +// It applies the partially accumulated behaviour in the accumulated batch +//------------------------------------------------------------------------------ +void Batch::EvolveInPartiallyAccumulatedBehaviourAccBatch(Simtime *_stime, BatchPlace *bp, double outputbatchlength, double _flow) +{ + length = ((density / (bp->GetDensity() - density)) * _stime->StepTime() *(bp->GetInstantaneousSpeed() - (_flow/bp->GetDensity()))) ; + density = bp->GetDensity(); + position = bp->GetLength() - outputbatchlength; +} + +//------------------------------------------------------------------------------ +// It applies the partially accumulated behaviour in the free batch +//------------------------------------------------------------------------------ +void Batch::EvolveInPartiallyAccumulatedBehaviourFreeBatch(Simtime *_stime, BatchPlace *bp, double outputbatchlength, double batch2length, double _flow) +{ + length = length +((bp->GetDensity() / (density - bp->GetDensity())) * _stime->StepTime() * (bp->GetInstantaneousSpeed() - (_flow/bp->GetDensity()))) ; + position = bp->GetLength() - outputbatchlength - batch2length; +} + + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Batch::Print(ostream &fout) +{ + fout << " (" << length << ", " << density << ", " << position << ")" << endl; +} + +//------------------------------------------------------------------------------ +// Write +//------------------------------------------------------------------------------ +void Batch::Write(ostream &fout) +{ + fout << " (" << length << ", " << density << ", " << position << ")" << endl; +} + diff --git a/src/bpn/batch.h b/src/bpn/batch.h new file mode 100644 index 0000000..3983ae7 --- /dev/null +++ b/src/bpn/batch.h @@ -0,0 +1,131 @@ +//====================================================================================// +// // +// Batch class // +// // +//====================================================================================// +// This File: batch.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 28/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 28/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef BATCH_H +#define BATCH_H + + +class Batch // batch.cpp +{ + public: + Batch(); + Batch(char *_name); + Batch(double _length, double _density, double _position); + Batch(double _inputflow, double _speed); + virtual ~Batch(); + + virtual batch_type IsA(){return Batch_bt;}; + char* GetName(); + void Copy(const Batch &_batch); + int IsEqual(const Batch &_batch); + + // input functions + void SetDensity(double _density); + void SetLength(double _length); + void SetPosition(double _position); + void MovePosition(double _length); + + // output functions + double GetDensity(); + double GetLength(); + double GetPosition(); + double GetOutputFlow(double _speed); + + // batch evolution functions + void EvolveInFreeBehaviour(Simtime *_stime, BatchPlace *bp); //RL + void EvolveInAccumulatedOuputBehaviour(Simtime *_stime, BatchPlace *bp, double _flow); //SA + void EvolveInFreeToAccumulatedBehaviourAccBatch(Simtime *_stime, BatchPlace *bp, double _flow); //RLAa + void EvolveInFreeToAccumulatedBehaviourFreeBatch(Simtime *_stime, BatchPlace *bp, double ouputbatchlength, double _flow); //RLAl + void EvolveInPartiallyAccumulatedBehaviourAccBatch(Simtime *_stime, BatchPlace *bp, double ouputbatchlength, double _flow); //RAPa1 + void EvolveInPartiallyAccumulatedBehaviourFreeBatch(Simtime *_stime, BatchPlace *bp, double outputbatchlength, double batch2length, double _flow); //RAPl + + //print function + virtual void Print(ostream &fout); + virtual void Write(ostream &fout); + + + protected: + simuleau_name name; + double length; + double density; + double position; + double outputflow; + + private: +}; + + +class ControllableBatch : public Batch // controllablebatch.cpp +{ + public: + typedef void (ControllableBatch::*EvolveFunction)(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); + + public: + ControllableBatch(); + ControllableBatch(char *_name); + ControllableBatch(double _length, double _density, double _position, double _speed); + ControllableBatch(double _inputflow, double _speed); + virtual ~ControllableBatch(); + + virtual batch_type IsA(){return Controllable_bt;}; + void Copy(const ControllableBatch &_controllablebatch); + int IsEqual(const ControllableBatch &_controllablebatch); + + + // input functions + void SetSpeed(double _speed); + void SetState(ctrl_batch_state _state); + void SetBehaviour(ctrl_batch_behaviour _behaviour); + + // output functions + double GetSpeed(); + double GetFlow(); + ctrl_batch_state GetState(); + ctrl_batch_state GetState(TriangularBatchPlace *tbp); + char* GetStateName(); + ctrl_batch_behaviour GetBehaviour(); + char* GetBehaviourName(); + + int IsOutputControllableBatch(BatchPlace *bp); + int IsInContactWithByFront(ControllableBatch &cb); + int IsInContactWithByRear(ControllableBatch &cb); + + + // controllable batch evolution functions + void SetEvolveFunction(EvolveFunction _func); + void Evolve(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); + + void EvolveInFreeBehaviour(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); //RL + void EvolveInCongestingOutputBehaviour(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); //RL + void EvolveInFreeToCongestingBehaviourCongBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); //RL + void EvolveInFreeToCongestingBehaviourFreeBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); //RL + void EvolveInFreeToCongestingBehaviourMiddlePlaceWithContactCongBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); //RL + void EvolveInFreeToCongestingBehaviourMiddlePlaceWithContactFreeBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); //RL + void EvolveInUncongestingOutputBehaviour(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); //RL + void EvolveInUncongestingToFreeBehaviourCongBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); //RL + void EvolveInUncongestingToFreeBehaviourFreeBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb); //RL + + + //print function + void Print(ostream &fout); + void Write(ostream &fout); + + + protected: + double speed; + ctrl_batch_state state; + ctrl_batch_behaviour behaviour; + EvolveFunction evolvefunction; + + private: +}; + +#endif // BATCH_H diff --git a/src/bpn/batchplace.cpp b/src/bpn/batchplace.cpp new file mode 100644 index 0000000..34e5f7d --- /dev/null +++ b/src/bpn/batchplace.cpp @@ -0,0 +1,1622 @@ +//====================================================================================// +// // +// Batch place classes inherit of place class // +// // +//====================================================================================// +// This File: batchplace.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Batch Place class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +BatchPlace::BatchPlace() +{ + behaviour = Free_behaviour; + formalisation = no; + speed = 0.0; + maxspeed = 0.0; + instantaneousspeed = 0.0; + density = 0.0; + length = 0.0; + + marks = new list<Batch>; + marks->clear(); + initialmarks = new list<Batch>; + initialmarks->clear(); + steadymarks = new list<Batch>; + steadymarks->clear(); + +} + +//------------------------------------------------------------------------------ +// Initialized Constructor +//------------------------------------------------------------------------------ +BatchPlace::BatchPlace(simuleau_name _name, double _speed, double _density, double _length):Place(_name) +{ + behaviour = Free_behaviour; + formalisation = no; + speed = _speed; + maxspeed = _speed; + instantaneousspeed = _speed; + density = _density; + length = _length; + + marks = new list<Batch>; + marks->clear(); + initialmarks = new list<Batch>; + initialmarks->clear(); + steadymarks = new list<Batch>; + steadymarks->clear(); + +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +BatchPlace::~BatchPlace() +{ + if (marks) + delete[] marks; + if (initialmarks) + delete[] initialmarks; + if (steadymarks) + delete[] steadymarks; +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void BatchPlace::Copy(const BatchPlace * _place) +{ + TransferNode(_place); + + conflict = _place->conflict; + structuralconflict = _place->structuralconflict; + + // batch place + behaviour = _place->behaviour; + formalisation = _place->formalisation; + + + density = _place->density; + speed = _place->speed; + maxspeed = _place->maxspeed; + instantaneousspeed = _place->instantaneousspeed; + + length = _place->length; + + marks = new list<Batch>; + marks->clear(); + + for (list<Batch>::iterator it=_place->marks->begin(); it!=_place->marks->end(); ++it) { + Batch *newbatch = new Batch; + newbatch->Copy(*it); + marks->push_back(*newbatch); + } + + initialmarks = new list<Batch>; + initialmarks->clear(); + + for (list<Batch>::iterator it=_place->initialmarks->begin(); it!=_place->initialmarks->end(); ++it) { + Batch *newbatch = new Batch; + newbatch->Copy(*it); + initialmarks->push_back(*newbatch); + } + + steadymarks = new list<Batch>; + steadymarks->clear(); + + for (list<Batch>::iterator it=_place->steadymarks->begin(); it!=_place->steadymarks->end(); ++it) { + Batch *newbatch = new Batch; + newbatch->Copy(*it); + steadymarks->push_back(*newbatch); + } + +} + +//------------------------------------------------------------------------------ +// It adds the initial marking of the place +//------------------------------------------------------------------------------ +void BatchPlace::AddBatchToInitialMarking(Batch &b) +{ + initialmarks->push_back(b); + marks->push_back(b); +} + +//------------------------------------------------------------------------------ +// It adds a batch to steady marking of the place +//------------------------------------------------------------------------------ +void BatchPlace::AddBatchToSteadyMarking(Batch &b) +{ + steadymarks->push_back(b); +} +//------------------------------------------------------------------------------ +// It adds a batch to marking of the place +//------------------------------------------------------------------------------ +void BatchPlace::AddBatchToMarking(Batch &b) +{ + marks->push_back(b); +} + +//------------------------------------------------------------------------------ +// It replace the current marking of a place +// TODO test this method +//------------------------------------------------------------------------------ +void BatchPlace::ChangeMarks(list<Batch> *lb) +{ + marks->clear(); + delete marks; + marks = lb; +} + +//------------------------------------------------------------------------------ +// It sets the new speed +//------------------------------------------------------------------------------ +void BatchPlace::SetSpeed(double _speed) +{ + speed = _speed; + instantaneousspeed = _speed; +} + +//------------------------------------------------------------------------------ +// It sets the new maximum speed +//------------------------------------------------------------------------------ +void BatchPlace::SetMaxSpeed(double _maxspeed) +{ + maxspeed = _maxspeed; +} + +//------------------------------------------------------------------------------ +// It sets the new density +//------------------------------------------------------------------------------ +void BatchPlace::SetDensity(double _density) +{ + density = _density; +} + +//------------------------------------------------------------------------------ +// It sets the new length +//------------------------------------------------------------------------------ +void BatchPlace::SetLength(double _length) +{ + length = _length; +} + +//------------------------------------------------------------------------------ +// It returns the current speed +//------------------------------------------------------------------------------ +double BatchPlace::GetSpeed() +{ + return (speed); +} + +//------------------------------------------------------------------------------ +// It returns the maximum/initial speed +//------------------------------------------------------------------------------ +double BatchPlace::GetMaxSpeed() +{ + return (maxspeed); +} + + +//------------------------------------------------------------------------------ +// It returns the instantaneous speed +//------------------------------------------------------------------------------ +double BatchPlace::GetInstantaneousSpeed() +{ + return (instantaneousspeed); +} + +//------------------------------------------------------------------------------ +// It returns the current density +//------------------------------------------------------------------------------ +double BatchPlace::GetDensity() +{ + return (density); +} + +//-------------------Near-optimal--------------------------------------------------------- +// It returns the free steady marking quantity +//----------------------------------------------------------------------------- +double BatchPlace::GetSteadyDensity() +{ + double steadydensity; + + if (steadymarks->size() != 0){ + for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->end();b++) { + steadydensity = b->GetDensity(); + } + } + return(steadydensity); +} + + + + +//------------------------------------------------------------------------------ +// It returns the length +//------------------------------------------------------------------------------ +double BatchPlace::GetLength() +{ + return (length); +} + +//------------------------------------------------------------------------------ +// It returns the place flow +//------------------------------------------------------------------------------ +double BatchPlace::GetOutputFlow() +{ + double outputflow = 0.0; + list<Batch>::iterator b; + + if(!HasOutputBatch()) + return outputflow; + + b = marks->begin(); + outputflow = b->GetOutputFlow(instantaneousspeed); + + return outputflow; +} + +//-----------------------------MCFF------------------------------------------------- +// It returns the place steadyinputflow or output flow in a place +//------------------------------------------------------------------------------ +double BatchPlace::GetSteadyPlaceFlow() +{ + double steadyplaceflow = 0.0; + Transition *t; + Flow *f; + + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ + t = (Transition*)inputnodes[i]; + f = t->GetFlow(); + steadyplaceflow += f->GetSteadyFlow(); + } + } + return (steadyplaceflow); +} + + +//------------------------------------------------------------------------------ +// It returns the place marks +//------------------------------------------------------------------------------ +list<Batch>* BatchPlace::GetMarking() +{ + return (marks); +} + +//------------------------------------------------------------------------------ +// It returns the place initial marks +//------------------------------------------------------------------------------ +list<Batch>* BatchPlace::GetInitialMarking() +{ + return (initialmarks); +} + +//------------------------------------------------------------------------------ +// It returns the place steady marks +//------------------------------------------------------------------------------ +list<Batch>* BatchPlace::GetSteadyMarking() +{ + return (steadymarks); +} + +//-------------------------------------- +//It returns the quantity +//-------------------------------------- +double BatchPlace::GetInitialQuantity() +{ + if (marks->size() != 0){ + for (list<Batch>::iterator b=marks->begin(); b!=marks->end(); b++) { + quantity += b->GetDensity() * b->GetLength(); + } + } + return(quantity); +} + +//---------------------------------------------------------------------------- +// It returns the free steady marking quantity +//----------------------------------------------------------------------------- +double BatchPlace::GetFreeSteadyQuantity() +{ + + double freesteadyquantity = 0.0; + double steadyplaceflow; + + Flow *f; + Transition *t; + + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ + t = (Transition*)inputnodes[i]; + f = t->GetFlow(); + steadyplaceflow += f->GetSteadyFlow(); + } + } + + if (steadymarks->size() == 1){ + for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->end();b++) { + if (b->GetDensity() == steadyplaceflow / maxspeed ){ + freesteadyquantity = b->GetDensity() * b->GetLength(); + } + else{ + freesteadyquantity = 0; + } + } + } + if (steadymarks->size() == 2){ + for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->end(); b++){ + freesteadyquantity = b->GetDensity() * b->GetLength(); + } + } + return(freesteadyquantity); +} + +//---------------------------------------------------------------------------- +// It returns the steady marking quantity +//----------------------------------------------------------------------------- + +double BatchPlace::GetSteadyQuantity() +{ + + if (steadymarks->size() != 0){ + for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->end(); b++) { + steadyquantity += b->GetDensity() * b->GetLength(); + } + return(steadyquantity); + +} +} + + + +//------------------------------------------------------------------------------ +// It returns the place behaviour +//------------------------------------------------------------------------------ +int BatchPlace::GetBehaviour() +{ + return (behaviour); +} + +//------------------------------------------------------------------------------ +// It returns the place behaviour +// We suppose only one output transition +// TODO verify if two or more tranistion +//------------------------------------------------------------------------------ +double BatchPlace::GetFlowOfOutputTransition() +{ + double outputtransitionflow = -1.0; + + Transition *t; + Flow *f; + + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ + t = outputnodes[i]; + switch (t->IsA()){ + case Batch_tr: f = t->GetFlow(); + outputtransitionflow = f->GetCurrentFlow(); + break; + } + } + } + return (outputtransitionflow); +} + +//------------------------------------------------------------------------------ +// It returns the output flow of all input transitions. +//------------------------------------------------------------------------------ +double BatchPlace::GetInputTransitonsFlow() +{ + double inflow = 0.0; + Transition *t; + Flow *f; + + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0.0){ + t = inputnodes[i]; + f = t->GetFlow(); + inflow += f->GetCurrentFlow(); + } + } + + return (inflow); +} + + +//------------------------------------------------------------------------------ +// It returns the output flow of all output transitions +//------------------------------------------------------------------------------ +double BatchPlace::GetOutputTransitonsFlow() +{ + double outflow = 0.0; + Transition *t; + Flow *f; + + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ + t = outputnodes[i]; + f = t->GetFlow(); + outflow += f->GetCurrentFlow(); + } + } + + return (outflow); +} + +//------------------------------------------------------------------------------ +// It returns true if the place has an output batch +//------------------------------------------------------------------------------ +int BatchPlace::HasOutputBatch() +{ + int result; + + Batch b; + + if (marks->size() == 0){ + result = 0; + } + else{ + b = marks->front(); + if ((length - b.GetPosition()) <= PRF::prf.Min_Err()){ + result = 1; + } + else{ + result = 0; + } + } + return (result); +} + + +//------------------------------------------------------------------------------ +// It returns the output batch +//------------------------------------------------------------------------------ +Batch* BatchPlace::GetOutputBatch() +{ + return (&marks->front()); +} + +//------------------------------------------------------------------------------ +// It returns the density of the output batch +//------------------------------------------------------------------------------ +double BatchPlace::GetDensityOutputBatch() +{ + double densityoutputbatch = 0.0; + Batch *b; + + if (HasOutputBatch()){ + b = GetOutputBatch(); + densityoutputbatch = b->GetDensity(); + } + return (densityoutputbatch); +} + +//------------------------------------------------------------------------------ +// It returns true if the batch place is full +//------------------------------------------------------------------------------ +int BatchPlace::IsFull() +{ + double full = length * density; + quantity = 0.0; + + if (marks->size() != 0){ + for (list<Batch>::iterator b=marks->begin(); b!=marks->end(); b++) { + quantity += b->GetDensity() * b->GetLength(); + } + if (abs(quantity - full) < PRF::prf.Min_Err()){ + return 1; + } + else{ + return 0; + } + } + else { + return 0; + } +} + +//===========================ON/Off============================================== +//------------------------------------------------------------------------------ +// It returns true if the batch place reaches steady marking quantity +//------------------------------------------------------------------------------ +int BatchPlace::IsEqualSteadyQuantity() +{ + ComputeQuantities(); + + if (abs(quantity - steadyquantity) < PRF::prf.Min_Err()){ + return 1; + } + else{ + return 0; + } +} + + +//------------------------------------------------------------------------------ +// It returns true if the marking quantity is greater than steady marking quantity +//------------------------------------------------------------------------------ +int BatchPlace::IsGreaterThanSteadyQuantity() +{ + ComputeQuantities(); + if ((quantity - steadyquantity) > PRF::prf.Min_Err()){ + return 1; + } + else{ + return 0; + } +} + + +//------------------------------------------------------------------------------ +// It returns true if the marking quantity is less than steady marking quantity +//------------------------------------------------------------------------------ +int BatchPlace::IsLessThanSteadyQuantity() +{ + + ComputeQuantities(); + + if (((abs(quantity - steadyquantity) > PRF::prf.Min_Err()) && ((quantity - steadyquantity) < 0.0))){ + return 1; + } + else{ + return 0; + } +} + +//------------------------------------------------------------------------------ +// It returns true if the marking is equal than steady marking +//------------------------------------------------------------------------------ +int BatchPlace::IsSteadyMarkingReached() +{ + if (steadymarks->size() != marks->size()) + return 0; + + list<Batch>::iterator b=marks->begin(); + if (steadymarks->size() != 0){ + for (list<Batch>::iterator sb=steadymarks->begin() ; sb!=steadymarks->end(); ++b,++sb) { + if(!sb->IsEqual(*b)) + return 0; + } + } + + return 1; +} +//============================================================================== + + +//===================Vecos================================================== +// It returns ture if the marking of continuous place is equal to steady marking +// and all of its input and output transition belongs to T_Z. +//========================================================================== +int BatchPlace::IsSteadyMarkingQuantityReachedandInputOutputTransitionBelongTz() +{ + Transition *t; + double weight; + int placestate =0; + int counter = 0; + int countertz=0; + + ComputeQuantities(); + + if (abs(steadyquantity - quantity) < PRF::prf.Min_Err()){ + if (GetNumberOfOutputArcs() == 0){ + return 1; // the conservative net and consistent net + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t=outputnodes[i]; + counter++; + } + if (outputarcs[i] != 0.0 && t->IsFiringQuantityOnState()==0) + countertz++; + + } + } + + if (GetNumberOfInputArcs() == 0){ + return 1; // the conservative net and consistent net + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t=inputnodes[i]; + counter++; + } + if (inputarcs[i] != 0.0 && t->IsFiringQuantityOnState()==0) + countertz++; + + } + } + if (counter == countertz) + return 1; + return placestate; + } + return placestate; +} + + + + + + + + + + +//------------------------------------------------------------------------------ +// It computes the state of the batch place +//------------------------------------------------------------------------------ +void BatchPlace::ComputeState() +{ + if (marks->empty()){ + state = 0.0; + } + else{ + if (HasOutputBatch() == 1){ + state = 1.0; + } + else{ + state = 0.0; + } + } +} + +//------------------------------------------------------------------------------ +// It creates a batch if the place has a least an input transition (continuous or batch) +// and the input flow is non-null +// It returns a positive value if a batch was created and 0 otherwise +// TODO verify multiple input transitions +//------------------------------------------------------------------------------ +int BatchPlace::CreateBatches() +{ + double inputtransflow = 0.0; + int result = 0; + + Transition *t; + Flow *f; + Batch *newb; + + formalisation = no; + + if (GetNumberOfInputArcs() != 0){ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0.0){ + t = inputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: f = t->GetFlow(); + inputtransflow = f->GetCurrentFlow(); + if (inputtransflow > 0.0){ + if (!marks->empty()){ + Batch &b = marks->back(); + if ((b.GetLength() != 0.0 ) && (b.GetPosition() != 0.0)){ + newb = new Batch(inputtransflow, instantaneousspeed); + AddBatchToMarking(*newb); + i = numberofarcs; + result += 1; + } + } + else{ + newb = new Batch(inputtransflow, instantaneousspeed); + AddBatchToMarking(*newb); + i = numberofarcs; + result += 1; + } + } + break; + } + } + } + } +} + +//------------------------------------------------------------------------------ +// It merges the batch that have the same speed and density and are in contact +//------------------------------------------------------------------------------ +void BatchPlace::MergeBatches() +{ + int merged = 0; + double endposition; + double newlength; + int numberofbatches = marks->size(); + Batch *newbatch; + list<Batch> *newmarks = new list<Batch>; + list<Batch>::iterator b1, b2, bi; + + if (numberofbatches > 1){ + b1 = marks->begin(); + bi = marks->begin(); + bi++; + for (int i=1; i<numberofbatches; i++){ + endposition = b1->GetPosition() - b1->GetLength(); + b2 = bi; + + if ((abs(b1->GetDensity() - b2->GetDensity()) < PRF::prf.Min_Err()) && + (abs(b2->GetPosition() - endposition) < PRF::prf.Min_Err())){ // merge batches + newlength = b1->GetLength() + b2->GetLength(); + b1->SetLength(newlength); + bi++; + merged = 1; + } + else{ + newbatch = new Batch; + newbatch->Copy(*b1); + newmarks->push_back(*newbatch); + b1 = b2; + bi++; + merged = 0; + } + } + + newbatch = new Batch; + if (merged){ + newbatch->Copy(*b1); + } + else{ + newbatch->Copy(*b2); + } + + newmarks->push_back(*newbatch); + marks->clear(); + marks = newmarks; + } +} + +//------------------------------------------------------------------------------ +// It destructs the batches that have a length or density equal to 0 and are not +// the input batch (position equal to length) +//------------------------------------------------------------------------------ +void BatchPlace::DestructBatches() +{ + int numberofbatches = marks->size(); + Batch *newbatch; + list<Batch> *newmarks = new list<Batch>; + list<Batch>::iterator b1; + + double batchquantity = 1.0; + + if (numberofbatches != 0){ + for (b1=marks->begin(); b1!=marks->end(); ++b1) { + batchquantity = b1->GetDensity() * b1->GetLength() ; +// last next date + if ((b1->GetPosition() - PRF::prf.Min_Err() ) > length){ + b1->SetLength(0.0); + b1->SetPosition(length); + } +// end + +// maybe compute batchquantity as a pourcentage of the total place capacity + + if (((b1->GetLength() > PRF::prf.Min_Err()) || (batchquantity > (PRF::prf.Min_Err()/10))) || ((b1->GetPosition() == 0.0) && (b1->GetLength() == 0.0))){ + newbatch = new Batch; + newbatch->Copy(*b1); + newmarks->push_back(*newbatch); + } + } + marks->clear(); + marks = newmarks; + } +} + +//------------------------------------------------------------------------------ +// It destructs the batches that have a length or density equal to 0 and are not +// the input batch (position equal to length) +//------------------------------------------------------------------------------ +void BatchPlace::ComputeQuantities() +{ + steadyquantity = 0.0; + quantity = 0.0; + + if (steadymarks->size() != 0){ + for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->end(); b++) { + steadyquantity += b->GetDensity() * b->GetLength(); + } + } + + if (marks->size() != 0){ + for (list<Batch>::iterator b=marks->begin(); b!=marks->end(); b++) { + quantity += b->GetDensity() * b->GetLength(); + } + } +} + + + +//--------------------------------------------------------------------------------------------- +// It computes that two types of quantity in the free part and accumulated part of steady state. +//---------------------------------------------------------------------------------------------- +//void BatchPlace::ComputeTwoTypesSteadyQuantities() +//{ +// steadyquantity = 0.0; +// double freesteadyquantity = 0.0; +// double accumulatedsteadyquantity = 0.0; +// +// +// if (steadymarks->size() != 0){ +// for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->end(); b++) { +// steadyquantity += b->GetDensity() * b->GetLength(); +// } +// } +// +// if (steadymarks->size() ==2){ +// for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->begin(); b++) { +// freesteadyquantity += b->GetDensity() * b->GetLength(); +// accumulatedsteadyquantity = steadyquantity-freesteadyquantity; +// } +// } +// if (steadymarks->size() ==1){ +// for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->begin(); b++){ +// if ( GetSteadyPlaceFlow() == b->GetDensity() * GetSpeed() ){ +// freesteadyquantity = b->GetDensity() * b->GetLength(); +// accumulatedsteadyquantity = 0.0; +// } +// else{ +// freesteadyquantity = 0.0; +// accumulatedsteadyquantity = b->GetDensity() * b->GetLength(); +// } +// } +// } +// } + + +//------------------------------------------------------------------------------ +// It computes the behaviour of a batch place +// TODO all batch places have no structural conflit +//------------------------------------------------------------------------------ +void BatchPlace::ComputeBehaviour() +{ + double outputtransitionflow; + double outputtransitionflowth; + Transition *t; + Flow *f; + + if (state == 0.0){ + behaviour = Free_behaviour; + return; + } + + outputtransitionflow = GetOutputTransitonsFlow(); // all output transitions flow + outputtransitionflowth = GetOutputFlow(); + + if (outputtransitionflow < outputtransitionflowth){ + behaviour = Accumulating_behaviour; + } + else{ + behaviour = Free_behaviour; + } + +/* for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ + t = outputnodes[i]; + switch (t->IsA()){ + case Batch_tr: f = t->GetFlow(); + //outputtransitionflow = f->GetCurrentFlow(); + ((BatchTransition*)t)->ComputeInputTheoreticalFlow(); + outputtransitionflowth = ((BatchTransition*)t)->GetInputTheoreticalFlow(); + if (outputtransitionflow < outputtransitionflowth){ + behaviour = Accumulating_behaviour; + } + else{ + behaviour = Free_behaviour; + } + break; + } + } + }*/ +} + + +//------------------------------------------------------------------------------ +// It evolves the marks (batches) of the batch place +//------------------------------------------------------------------------------ +void BatchPlace::EvolveMarks(double _date) +{ + Batch *ob; + list<Batch>::iterator b; + + if (formalisation == yes) + return; + + if (behaviour == Free_behaviour){ + EvolveInFreeBehaviour(simulation->stime); + } + else{ + if (HasOutputBatch() == 1){ // place is in accumulating behaviour and has an output batch + ob = GetOutputBatch(); + if ((density - ob->GetDensity()) <= PRF::prf.Min_Err()){ // the output batch is full accumulated + if (marks->size() > 1){ // new marking depends of a second batch + b = marks->begin(); + b++; + if (b->GetPosition() > (length - ob->GetLength())){ + b->SetPosition(length - ob->GetLength()); + } + + if (abs(b->GetPosition() - (length - ob->GetLength())) <= PRF::prf.Min_Err()) { // two batches are in contact + EvolveInPartiallyAccumulatedBehaviour(simulation->stime); + } + else{ // batch are not in contact + EvolveInAccumulatedOutputBehaviour(simulation->stime); + } + } + else{ // only one batch + EvolveInAccumulatedOutputBehaviour(simulation->stime); + } + } + else{ // the output batch has a different density of the place density + EvolveInFreeToAccumulatedBehaviour(simulation->stime); + } + } + } + formalisation == yes; + steadyquantity = 0.0; + if (steadymarks->size() != 0){ + for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->end(); b++) { + steadyquantity += b->GetDensity() * b->GetLength(); + } + } + quantity = 0.0; + if (marks->size() != 0){ + for (list<Batch>::iterator b=marks->begin(); b!=marks->end(); b++) { + quantity += b->GetDensity() * b->GetLength(); + } + } + +} + +//------------------------------------------------------------------------------ +// It computes the date of the next event to a Batch becomes an Output Batch type +// returns -1.0 if no BOB event is possible +//------------------------------------------------------------------------------ +double BatchPlace::GetBOBEvent() +{ + double pos; + double date; + Batch b; + + if (marks->empty()){ + return (-1.0); // no event of this type + } + + if (state != 1.0){ + b = marks->front(); + pos = b.GetPosition(); + date = (length - pos) / instantaneousspeed; + date += simulation->stime->GetCurrentDate(); + return (date); + } + return (-1.0); +} + + +//------------------------------------------------------------------------------ +// It computes the date of the next event to a Destruction of an Output Batch type +//------------------------------------------------------------------------------ +double BatchPlace::GetDOBEvent() +{ + double date = -1.0; + double outputtransitionflow = GetOutputTransitonsFlow(); + Transition *t; + Flow *f; + Batch *b; + + if (HasOutputBatch() == 1){ + b = GetOutputBatch(); + if ((density - b->GetDensity()) > PRF::prf.Min_Err()){ + if ((behaviour == Free_behaviour) && (instantaneousspeed != 0.0)){ + date = simulation->stime->GetCurrentDate() + (b->GetLength()/instantaneousspeed); + } + } + else{ + if (outputtransitionflow != 0.0){ + date = b->GetLength() * density / outputtransitionflow; + date += simulation->stime->GetCurrentDate(); + } +/* for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ + t = outputnodes[i]; + switch (t->IsA()){ + case Batch_tr: f = t->GetFlow(); + outputtransitionflow = f->GetCurrentFlow(); + if (outputtransitionflow != 0.0){ + date = b->GetLength() * density / outputtransitionflow; + date += simulation->stime->GetCurrentDate(); + } + break; + } + } + } +*/ + } + } + return (date); +} + + +//------------------------------------------------------------------------------ +// It computes the date of the next event to a Full accumulation/congestion of a batch +// (Batch Becomes Dense) type +//------------------------------------------------------------------------------ +double BatchPlace::GetBBDEvent() +{ + double date = -1.0; + double outputtransitionflow = GetOutputTransitonsFlow(); + Transition *t; + Flow *f; + Batch *b; + + if (HasOutputBatch() == 1){ + b = GetOutputBatch(); + if ((density - b->GetDensity()) > PRF::prf.Min_Err()){ + if ((behaviour == Accumulating_behaviour)){ + if (((instantaneousspeed * density) - outputtransitionflow) != 0.0){ + date = b->GetLength() * (density - b->GetDensity()) / (instantaneousspeed * density - outputtransitionflow); + date += simulation->stime->GetCurrentDate(); + } + +/* + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ + t = outputnodes[i]; + switch (t->IsA()){ + case Batch_tr: f = t->GetFlow(); + outputtransitionflow = f->GetCurrentFlow(); + if (((instantaneousspeed * density) - outputtransitionflow) != 0.0){ + date = b->GetLength() * (density - b->GetDensity()) / (instantaneousspeed * density - outputtransitionflow); + date += simulation->stime->GetCurrentDate(); + } + break; + } + } + } +*/ + } + } + } + return (date); +} + + +//------------------------------------------------------------------------------ +// It computes the date of the next event to Two Batches Meet type +// TODO verify multiple output transitions +//------------------------------------------------------------------------------ +double BatchPlace::GetTBMEvent() +{ + double date = -1.0; + double outputtransitionflow = GetOutputTransitonsFlow(); + Transition *t; + Flow *f; + list<Batch>::iterator b; + Batch *outputbatch; + + if ((marks->size() < 2) || (HasOutputBatch() == 0)){ + return (date); + } + + outputbatch = GetOutputBatch(); + b = marks->begin(); + b++; + if (((density - outputbatch->GetDensity()) < PRF::prf.Min_Err()) && (behaviour == Accumulating_behaviour)){ + if (((length - outputbatch->GetLength()) - b->GetPosition()) > PRF::prf.Min_Err()){ + if ((instantaneousspeed * density - outputtransitionflow) != 0.0){ + date = (density * (length - outputbatch->GetLength() - b->GetPosition())/(instantaneousspeed * density - outputtransitionflow)); + date += simulation->stime->GetCurrentDate(); + } + + +/* for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ + t = outputnodes[i]; + switch (t->IsA()){ + case Batch_tr : f = t->GetFlow(); + outputtransitionflow = f->GetCurrentFlow(); + if ((instantaneousspeed * density - outputtransitionflow) != 0.0){ + date = (density * (length - outputbatch->GetLength() - b->GetPosition())/(instantaneousspeed * density - outputtransitionflow)); + date += simulation->stime->GetCurrentDate(); + } + break; + } + } + } +*/ + } + else{ + if (((density - b->GetDensity()) > PRF::prf.Min_Err()) && (instantaneousspeed != 0.0) && (density != 0.0) && (b->GetLength() != 0.0)){ +// outputtransitionflow = GetOutputTransitonsFlow(); + date = (density - b->GetDensity()) * b->GetLength()/(instantaneousspeed * density - outputtransitionflow); + date += simulation->stime->GetCurrentDate(); + } + } + } + return (date); +} + +//----------------- On off considered events------------------------------------------------- +// It computes the date of the next event to marking quantity of a batch place +// reaches its steady marking quantity (Place reaches Steady marking Quantity). +//------------------------------------------------------------------------------ +double BatchPlace::GetPSQEvent() +{ + double steadyquantity; // we need input this value before the simulation. !!! + double quantity = 0.0; + double date; + double transitionflow=0.0; + double weightflow=0.0; + Batch *b; + Transition *t; + Flow *f; + + if (steadymarks->size() != 0){ + for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->end(); b++) { + steadyquantity += b->GetDensity() * b->GetLength(); + } + } + + if (marks->size() != 0){ + for (list<Batch>::iterator b=marks->begin(); b!=marks->end(); b++) { + quantity += b->GetDensity() * b->GetLength(); + } + } + + if (abs(quantity - steadyquantity) < PRF::prf.Min_Err()){ + date= simulation->stime->GetCurrentDate(); + } + + else{ + if (GetNumberOfOutputArcs()){ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t = outputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: f = t->GetFlow(); + transitionflow = f->GetCurrentFlow(); + weightflow -= (outputarcs[i] * transitionflow); + break; + } + } + } + } + + if (GetNumberOfInputArcs()){ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ +// t = simulation->sbpn->GetTransition(i); + t = inputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: f = t->GetFlow(); + transitionflow = f->GetCurrentFlow(); + + weightflow += (inputarcs[i] * transitionflow); + + break; + } + } + } + } + + if ((weightflow != 0.0)){ + date = simulation->stime->GetCurrentDate() - ((quantity-steadyquantity)/weightflow); + } + return (date); +} +} + + + + + + + /* if (HasOutputBatch() == 1){ + b = GetOutputBatch(); + if ((density - b->GetDensity()) > PRF::prf.Min_Err()){ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ + t = outputnodes[i]; + switch (t->IsA()){ + case Batch_tr: u = t->GetFlow(); + outputtransitionflow = u->GetCurrentFlow(); + if (((instantaneousspeed * density) - outputtransitionflow) != 0.0){ + date = b->GetLength() * (density - b->GetDensity()) / (instantaneousspeed * density - outputtransitionflow); + date += simulation->stime->GetCurrentDate(); + } + break; + } + } + } + } + } + return (date); +} +} +*/ + +//-----------------------end---------------------------------------------------- + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void BatchPlace::Print(ostream& fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Batch" << endl; + fout << " Behaviour: " << behaviour << endl; + fout << " Density: " << density << endl; + fout << " Maximum speed: " << maxspeed << endl; + fout << " Speed: " << speed << endl; + fout << " Length: " << length << endl; + fout << " Initial Batches:" << initialmarks->size() << endl; + + for (list<Batch>::iterator it=initialmarks->begin(); it!=initialmarks->end(); ++it) { + it->Print(fout); + } + + if (!steadymarks->empty()){ + fout << " Steady Batches:" << steadymarks->size() << endl; + + for (list<Batch>::iterator it=steadymarks->begin(); it!=steadymarks->end(); ++it) { + it->Print(fout); + } + } + + fout << " Batches: " << marks->size() << endl; + + for (list<Batch>::iterator it=marks->begin(); it!=marks->end(); ++it) { + it->Print(fout); + } + + fout << " Arcs: " << endl; + PrintArcs(fout); +} + +//------------------------------------------------------------------------------ +// Write +//------------------------------------------------------------------------------ +void BatchPlace::Write(ostream &fout) +{ + ComputeQuantities(); + fout << "Name: " << name << endl; + fout << " Type: " << "Batch" << endl; + fout << " Density: " << density << endl; + fout << " Speed: " << speed << endl; + fout << " Length: " << length << endl; + fout << " Batches: " << marks->size() << ": " << quantity << endl; + + for (list<Batch>::iterator it=marks->begin(); it!=marks->end(); ++it) { + it->Write(fout); + } + + if (!steadymarks->empty()){ + fout << " Steady Batches:" << steadymarks->size() ; + if (IsSteadyMarkingReached()) + fout << "(steady marking reached) "; + fout << ": " << steadyquantity << endl; + + for (list<Batch>::iterator it=steadymarks->begin(); it!=steadymarks->end(); ++it) { + it->Write(fout); + } + } +} + +//------------------------------------------------------------------------------ +// It evolves the marking in a free behaviour +// old fonctionRL +//------------------------------------------------------------------------------ +void BatchPlace::EvolveInFreeBehaviour(Simtime *st) +{ + if (!marks->empty()){ + for (list<Batch>::iterator b = marks->begin(); b!=marks->end(); b++){ + b->EvolveInFreeBehaviour(st, this); + } + } +} + +//------------------------------------------------------------------------------ +// It evolves the marking in a accumulated output behaviour +// Non other batch in contact with the output batch +// old fonctionSA +// TODO verify structural conflit +//------------------------------------------------------------------------------ +void BatchPlace::EvolveInAccumulatedOutputBehaviour(Simtime *st) +{ + int i; + double flowofoutputtransition = GetOutputTransitonsFlow(); + Transition *t; + Flow *f; + list<Batch>::iterator b; + + if (!marks->empty()){ + for (i=0, b = marks->begin(); b!=marks->end(); b++, i++){ + if ((HasOutputBatch()) && (i == 0)){ // the accumulated output batch + b->EvolveInAccumulatedOuputBehaviour(st, this, flowofoutputtransition); +/* for (int j=0; j<numberofarcs; j++){ + if (outputarcs[j] != 0.0){ + t = outputnodes[j]; + switch (t->IsA()){ + case Batch_tr : f = t->GetFlow(); + flowofoutputtransition = f->GetCurrentFlow(); + b->EvolveInAccumulatedOuputBehaviour(st, this, flowofoutputtransition); + break; + } + } + } +*/ + + } + else{ + b->EvolveInFreeBehaviour(st, this); // other free batches + } + } + } + +} + +//------------------------------------------------------------------------------ +// It evolves the marking when it has an output batch and a second batch in contact not completely accumulated +// old fonctionRAP +//------------------------------------------------------------------------------ +void BatchPlace::EvolveInPartiallyAccumulatedBehaviour(Simtime *st) +{ + int i; + double flowofoutputtransition = GetOutputTransitonsFlow(); + double lengthofoutputbatch; + Batch *newbatch, *newbatch2; + Batch *outputbatch; + list<Batch> *newmarks = new list<Batch>; + list<Batch>::iterator b; + + newmarks->clear(); + + if (!marks->empty()){ + for (i=0, b = marks->begin(); b!=marks->end(); b++, i++){ + if ((HasOutputBatch()) && (i == 0)){ // output batch + b->EvolveInAccumulatedOuputBehaviour(st, this, flowofoutputtransition); + newbatch = new Batch; + newbatch->Copy(*b); + newmarks->push_back(*newbatch); + } + else{ + if (i == 1){ // first batch after output batch + outputbatch = GetOutputBatch(); + lengthofoutputbatch = outputbatch->GetLength(); + newbatch = new Batch; + newbatch->Copy(*b); + newbatch->EvolveInPartiallyAccumulatedBehaviourAccBatch(st, this, lengthofoutputbatch, flowofoutputtransition); + + newbatch2 = new Batch; + newbatch2->Copy(*b); + newbatch2->EvolveInPartiallyAccumulatedBehaviourFreeBatch(st, this, lengthofoutputbatch, newbatch->GetLength(), flowofoutputtransition); + + newmarks->push_back(*newbatch); + newmarks->push_back(*newbatch2); + } + else{ + newbatch = new Batch; + newbatch->Copy(*b); + newbatch->EvolveInFreeBehaviour(st, this); + newmarks->push_back(*newbatch); + } + } + } + marks->clear(); + marks = newmarks; + } +} + + +//------------------------------------------------------------------------------ +// It evolves the marking when the batch passe from free to accumulated +// old fonctionRLA +//------------------------------------------------------------------------------ +void BatchPlace::EvolveInFreeToAccumulatedBehaviour(Simtime *st) +{ + double outputtransitionflow = GetOutputTransitonsFlow();; + int i; + double lengthofoutputbatch; + Batch *newbatch, *newbatch2; + Batch outputbatch; + list<Batch> *newmarks = new list<Batch>; + list<Batch>::iterator b; + Transition *t; + Flow *f; + + if (!marks->empty()){ + for (i=0, b = marks->begin(); b!=marks->end(); b++, i++){ + if ((HasOutputBatch()) && (i == 0)){ // output batch + newbatch = new Batch; + newbatch->Copy(*b); + newbatch->EvolveInFreeToAccumulatedBehaviourAccBatch(st, this, outputtransitionflow); + + newbatch2 = new Batch; + newbatch2->Copy(*b); + newbatch2->EvolveInFreeToAccumulatedBehaviourFreeBatch(st, this, newbatch->GetLength(), outputtransitionflow); + + newmarks->push_back(*newbatch); + newmarks->push_back(*newbatch2); +/* for (int j=0; j<numberofarcs; j++){ + if (outputarcs[j] != 0.0){ + t = outputnodes[j]; + switch (t->IsA()){ + case Batch_tr : f = t->GetFlow(); + _flow = f->GetCurrentFlow(); + newbatch = new Batch; + newbatch->Copy(*b); + newbatch->EvolveInFreeToAccumulatedBehaviourAccBatch(st, this, _flow); + + newbatch2 = new Batch; + newbatch2->Copy(*b); + newbatch2->EvolveInFreeToAccumulatedBehaviourFreeBatch(st, this, newbatch->GetLength(), _flow); + + newmarks->push_back(*newbatch); + newmarks->push_back(*newbatch2); + break; + } + } + } +*/ + } + else{ + newbatch = new Batch; + newbatch->Copy(*b); + newbatch->EvolveInFreeBehaviour(st, this); + newmarks->push_back(*newbatch); + } + } + marks->clear(); + marks = newmarks; + } +} + +//-----------------------------------Near-optimal case--------------------------------------------- +// It returns ture if the batch place satisies the conditions. +// condition: 1) It has an output batch whose density greater than d_i^s +// 2) The last several batches having marking quantity greater than free steady marking quantity -mininus the quantity of +// first steady batch +// 3) Before output batch is destroyed, the next batch becomes output batch, we assume that it keeps a steady output flow value. +//-------------------------------------------------------------------------------------------------- +int BatchPlace::IsHoldSteadyPlaceFlowUntilSteadyState() +{ + double frontquantity; + double remainingfreesteadyquantity; + double currentfreesteadyquantity; + int placestate = 0; + Transition *t; + list<Batch>::iterator bl; + Batch *outputbatch; + Batch bf; + + if ((marks->size() == 0) || (HasOutputBatch() == 0) || (IsSteadyMarkingQuantityReachedandInputOutputTransitionBelongTz() == 1)){ + return 0; + } + bl = marks->begin(); + + if (bl->GetDensity() != GetSteadyDensity()){ + currentfreesteadyquantity = 0; + } + else{ + currentfreesteadyquantity = bl->GetDensity() * bl->GetLength(); + } + + + outputbatch = GetOutputBatch(); + bf = marks->front(); + + if (GetSteadyDensity() >= outputbatch->GetDensity() ){ + frontquantity = outputbatch->GetDensity() * outputbatch->GetLength(); + if (frontquantity >= (GetFreeSteadyQuantity()-currentfreesteadyquantity)){ + // bf++; + } + } +} + +// if (((length - outputbatch->GetLength()) - b->GetPosition()) > PRF::prf.Min_Err()){ +// if ((instantaneousspeed * density - outputtransitionflow) != 0.0){ +// date = (density * (length - outputbatch->GetLength() - b->GetPosition())/(instantaneousspeed * density - outputtransitionflow)); +// date += simulation->stime->GetCurrentDate(); +// } +// +//// +//// +//// +////} +// +// +////int BatchPlace::IsSteadyMarkingQuantityReachedandInputOutputTransitionBelongTz() +////{ +//// Transition *t; +//// double weight; +//// int placestate =0; +//// int counter = 0; +//// int countertz=0; +//// +//// ComputeQuantities(); +//// +//// if (abs(steadyquantity - quantity) < PRF::prf.Min_Err()){ +//// if (GetNumberOfOutputArcs() == 0){ +//// return 1; // the conservative net and consistent net +//// } +//// else{ +//// for (int i=0; i<numberofarcs; i++){ +//// if (outputarcs[i] != 0.0){ +////// t = simulation->sbpn->GetTransition(i); +//// t=outputnodes[i]; +//// counter++; +//// } +//// if (outputarcs[i] != 0.0 && t->IsFiringQuantityOnState()==0) +//// countertz++; +//// +//// } +//// } +//// +//// if (GetNumberOfInputArcs() == 0){ +//// return 1; // the conservative net and consistent net +//// } +//// else{ +//// for (int i=0; i<numberofarcs; i++){ +//// if (inputarcs[i] != 0.0){ +////// t = simulation->sbpn->GetTransition(i); +//// t=inputnodes[i]; +//// counter++; +//// } +//// if (inputarcs[i] != 0.0 && t->IsFiringQuantityOnState()==0) +//// countertz++; +//// +//// } +//// } +//// if (counter == countertz) +//// return 1; +//// return placestate; +//// } +//// return placestate; +////} +// steadyquantity = 0.0; +// double freesteadyquantity = 0.0; +// double accumulatedsteadyquantity = 0.0; +// +// +// if (steadymarks->size() != 0){ +// for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->end(); b++) { +// steadyquantity += b->GetDensity() * b->GetLength(); +// } +// } +// +// if (steadymarks->size() ==2){ +// for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->begin(); b++) { +// freesteadyquantity += b->GetDensity() * b->GetLength(); +// steadydensity=b->GetInstan +// accumulatedsteadyquantity = steadyquantity-freesteadyquantity; +// } +// } +// if (steadymarks->size() ==1){ +// for (list<Batch>::iterator b=steadymarks->begin(); b!=steadymarks->begin(); b++){ +// if ( p->GetSteadyPlaceFlow() == b->GetDensity() * p->GetSpeed() ){ +// freesteadyquantity = b->GetDensity() * b->GetLength(); +// accumulatedsteadyquantity = 0.0; +// } +// else{ +// freesteadyquantity = 0.0; +// accumulatedsteadyquantity = b->GetDensity() * b->GetLength(); +// } +// } +// } + + + diff --git a/src/bpn/batchtransition.cpp b/src/bpn/batchtransition.cpp new file mode 100644 index 0000000..b1766f4 --- /dev/null +++ b/src/bpn/batchtransition.cpp @@ -0,0 +1,269 @@ + +//====================================================================================// +// // +// Batch transition classes inherit of continuous transition class // +// // +//====================================================================================// +// This File: batchtransition.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Batch Transition class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +BatchTransition::BatchTransition():ContinuousTransition() +{ + inputtheoreticalflow = -1.0; + outputtheoreticalflow = -1.0; +} + +//------------------------------------------------------------------------------ +// Initialized Constructor +//------------------------------------------------------------------------------ +BatchTransition::BatchTransition(simuleau_name _name, double _flow, double _steadyflow):ContinuousTransition(_name, _flow, _steadyflow) +{ + inputtheoreticalflow = -1.0; + outputtheoreticalflow = -1.0; +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +BatchTransition::~BatchTransition() +{ + if (flow) + delete flow; +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void BatchTransition::Copy(const BatchTransition *_transition) +{ + TransferNode(_transition); + flow = new Flow; + flow->Copy(_transition->flow); // transition flows + firingquantity = new FiringQuantity; + firingquantity->Copy(_transition->firingquantity); + inputtheoreticalflow = _transition->inputtheoreticalflow; + outputtheoreticalflow = _transition->outputtheoreticalflow; +} + +//------------------------------------------------------------------------------ +// It returns the input theoretical flow +//------------------------------------------------------------------------------ +double BatchTransition::GetInputTheoreticalFlow() +{ + return (inputtheoreticalflow); +} + +//------------------------------------------------------------------------------ +// It returns the output theoretical flow +//------------------------------------------------------------------------------ +double BatchTransition::GetOutputTheoreticalFlow() +{ + return (outputtheoreticalflow); +} + +//------------------------------------------------------------------------------ +// It computes the input theoretical flow +//------------------------------------------------------------------------------ +void BatchTransition::ComputeInputTheoreticalFlow() +{ + BatchPlace *p; + list<Batch>::iterator b; + list<Batch> *placemarks; + + double placespeed; + double placestate; + + + if (GetNumberOfInputArcs() == 0){ + inputtheoreticalflow = -1.0; // no input place, infinite flow + return; + } + + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0.0){ + p = inputnodes[i]; + switch (p->IsA()){ + case Batch_pl: + case Triangular_pl: placestate = p->GetState(); + if (placestate == 1.0){ // test for output batch + placespeed = p->GetInstantaneousSpeed(); + placemarks = p->GetMarking(); + b = placemarks->begin(); + inputtheoreticalflow = b->GetOutputFlow(placespeed); + } + else{ + inputtheoreticalflow = 0.0; + } + i = numberofarcs; + break; + default: inputtheoreticalflow = -1.0; + break; + } + } + } +} + +//------------------------------------------------------------------------------ +// It computes the output theoretical flow +// TODO verify why only one conection is used +//------------------------------------------------------------------------------ +void BatchTransition::ComputeOutputTheoreticalFlow() +{ + BatchPlace *p; + double placespeed; + double placedensity; + + if (GetNumberOfOutputArcs() == 0){ + outputtheoreticalflow = -1.0; // no input place, infinite flow + return; + } + + outputtheoreticalflow = -1.0; + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ + p = outputnodes[i]; + switch (p->IsA()){ + case Batch_pl: + case Triangular_pl: placespeed = p->GetSpeed(); + placedensity = p->GetDensity(); + outputtheoreticalflow = placedensity * placespeed; + break; + } + } + } +} + + +//------------------------------------------------------------------------------ +// It computes the transition theoretical flow +//------------------------------------------------------------------------------ +void BatchTransition::ComputeTheoreticalFlow() +{ + double flowvalue; + + if (state == 0.0){ + flow->SetTheoreticalFlow(0.0); + return; + } + + ComputeInputTheoreticalFlow(); + ComputeOutputTheoreticalFlow(); + if (state == 1.0){ + flowvalue = ComputeMinimumFlow(flow->GetMaximumFlow(), inputtheoreticalflow); + flowvalue = ComputeMinimumFlow(flowvalue, outputtheoreticalflow); + } + else{ + flowvalue = ComputeMinimumFlow(flow->GetMaximumFlow(), inputtheoreticalflow); + flowvalue = ComputeMinimumFlow(flowvalue, outputtheoreticalflow); + flowvalue = ComputeMinimumFlow(flowvalue, ComputeTheoreticalFlowOfPlace()); + } + flow->SetTheoreticalFlow(flowvalue); +} + + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void BatchTransition::Print(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Batch" << endl; + fout << " Flow: " << endl; + flow->Print(fout); + fout << " Arcs: " << endl; + PrintArcs(fout); +} + +//------------------------------------------------------------------------------ +// It writes the transition flows +//------------------------------------------------------------------------------ +void BatchTransition::Write(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Batch" << endl; + fout << " State: " << state << endl; + fout << " Current Flow: " << flow->GetCurrentFlow() << endl; + if (flow->GetSteadyFlow() != -1.0) + fout << " Steady Flow: " << flow->GetSteadyFlow() << endl; +} + + +//========================RBF========Event================================= +// It gets the rbf event. (a new ) objective : +//=========================================================================== +double BatchTransition::GetRBFEvent() +{ + double date; + double min_date=-1.0; + double weight; + double transitionflow; + Place *p; +// Transition *t; +// FiringQuantity *q; + double Zs; + double z; + + // q=t->GetFiringQuantity(); + Zs=firingquantity->GetSteadyFiringQuantity(); + z =firingquantity->GetCurrentFiringQuantity(); + + if (GetNumberOfOutputArcs() == 0){ + return (-1.0); + } + else if(z >= Zs){ + return (-1.0); + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ +// p = simulation->sbpn->GetPlace(i); + p = (Place*)outputnodes[i]; + + weight = outputarcs[i]; + // f=t->GetFlow(); + transitionflow=flow->GetCurrentFlow(); + switch (p->IsA()){ + case Continuous_pl : + date = (Zs-z) / transitionflow; // FreeSteadyMarkingQuantity= 0 in P^C + date += simulation->stime->GetCurrentDate(); + + break; + case Batch_pl : + date = (Zs-z -(((BatchPlace*)p)->GetFreeSteadyQuantity() / weight)) / transitionflow; + if (date < 0){ + return (-1.0); + } + else{ + date += simulation->stime->GetCurrentDate(); + + } + break; + + } + + if (date < min_date || min_date==-1.0){ + min_date= date; + } + } + + + } + return (min_date); + } + return (-1.0); +} +//----------------------------------------------------------------------------------- diff --git a/src/bpn/bpn.cpp b/src/bpn/bpn.cpp new file mode 100644 index 0000000..539a626 --- /dev/null +++ b/src/bpn/bpn.cpp @@ -0,0 +1,4117 @@ + +//====================================================================================// +// // +// Batch Petri Nets main class // +// // +//====================================================================================// +// This File: bpn.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 21/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 21/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +// Empty contructor +//------------------------------------------------------------------------------ +BPN::BPN() +{ + strcpy(bpnname,""); + + numberofdiscreteplaces = 0; + numberofcontinuousplaces = 0; + numberofbatchplaces = 0; + numberoftriangularplaces = 0; + + numberofdiscretetransitions = 0; + numberofcontinuoustransitions = 0; + numberofbatchtransitions = 0; + + places = NULL; + transitions = NULL; +} + +//------------------------------------------------------------------------------ +// Sized contructor +//------------------------------------------------------------------------------ +BPN::BPN(const int _numberofplaces, const int _numberoftransitions) +{ + strcpy(bpnname,""); + + numberofdiscreteplaces = 0; + numberofcontinuousplaces = 0; + numberofbatchplaces = 0; + numberoftriangularplaces = 0; + + numberofdiscretetransitions = 0; + numberofcontinuoustransitions = 0; + numberofbatchtransitions = 0; + + places = new Place* [_numberofplaces]; + for (int i=0; i<_numberofplaces; i++) + places[i] = NULL; + + transitions = new Transition* [_numberoftransitions]; + for (int i=0; i<_numberoftransitions; i++) + transitions[i] = NULL; +} + + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +BPN::~BPN() +{ + if (places) + delete [] places; + if (transitions) + delete [] transitions; +} + + +//------------------------------------------------------------------------------ +// copy +//------------------------------------------------------------------------------ +void BPN::Copy(const BPN * _bpn) +{ + strcpy(bpnname, _bpn->bpnname); + + numberofdiscreteplaces = _bpn->numberofdiscreteplaces; + numberofcontinuousplaces = _bpn->numberofcontinuousplaces; + numberofbatchplaces = _bpn->numberofbatchplaces; + numberoftriangularplaces = _bpn->numberoftriangularplaces; + + numberofdiscretetransitions = _bpn->numberofdiscretetransitions; + numberofcontinuoustransitions = _bpn->numberofcontinuoustransitions;; + numberofbatchtransitions = _bpn->numberofbatchtransitions;; + + places = new Place* [NumberOfPlaces()]; + + int j = 0; + int k = numberofdiscreteplaces; + for (int i=j; i<k; i++){ + DiscretePlace *place = new DiscretePlace; + place->Copy(_bpn->places[i]); + places[i] = place; + } + + j = k; + k += numberofcontinuousplaces; + for (int i=j; i<k; i++){ + ContinuousPlace *place = new ContinuousPlace; + place->Copy(_bpn->places[i]); + places[i] = place; + } + + j = k; + k += numberofbatchplaces; + for (int i=j; i<k; i++){ + BatchPlace *place = new BatchPlace; + place->Copy(_bpn->places[i]); + places[i] = place; + } + + j = k; + k += numberoftriangularplaces; + for (int i=j; i<k; i++){ + TriangularBatchPlace *place = new TriangularBatchPlace; + place->Copy(_bpn->places[i]); + places[i] = place; + } + + transitions = new Transition* [NumberOfTransitions()]; + + j = 0; + k = numberofdiscretetransitions; + for (int i=j; i<k; i++){ + DiscreteTransition *transition = new DiscreteTransition; + transition->Copy(_bpn->transitions[i]); + transitions[i] = transition; + } + + j = k; + k += numberofcontinuoustransitions; + for (int i=j; i<k; i++){ + ContinuousTransition *transition = new ContinuousTransition; + transition->Copy(_bpn->transitions[i]); + transitions[i] = transition; + } + + j = k; + k += numberofbatchtransitions; + for (int i=j; i<k; i++){ + BatchTransition *transition = new BatchTransition; + transition->Copy(_bpn->transitions[i]); + transitions[i] = transition; + } + + //update node pointes + for (int i=0; i<NumberOfPlaces(); i++){ + places[i]->AddInputNodes(transitions); + places[i]->AddOutputNodes(transitions); + } + + for (int i=0; i<NumberOfTransitions(); i++){ + transitions[i]->AddInputNodes(places); + transitions[i]->AddOutputNodes(places); + } + +} + +//------------------------------------------------------------------------------ +// It allocs input/output array for nodes +//------------------------------------------------------------------------------ +void BPN::AllocArcs() +{ + for (int i=0; i<NumberOfPlaces(); i++) + places[i]->AllocArcs(NumberOfTransitions()); + + for (int i=0; i<NumberOfTransitions(); i++) + transitions[i]->AllocArcs(NumberOfPlaces()); +} + +//------------------------------------------------------------------------------ +// It links input/output arc to nodes +//------------------------------------------------------------------------------ +void BPN::AddNodeLinks() +{ + //update node pointes + for (int i=0; i<NumberOfPlaces(); i++){ + places[i]->AddInputNodes(transitions); + places[i]->AddOutputNodes(transitions); + } + + for (int i=0; i<NumberOfTransitions(); i++){ + transitions[i]->AddInputNodes(places); + transitions[i]->AddOutputNodes(places); + } +} + +//------------------------------------------------------------------------------ +// It assigns a name to the model +//------------------------------------------------------------------------------ +void BPN::PutName(simuleau_name _name) +{ + strcpy(bpnname, _name); +} + +//------------------------------------------------------------------------------ +// It set the number of discrete places in the model +//------------------------------------------------------------------------------ +void BPN::NumberOfDiscretePlaces(const int n) +{ + numberofdiscreteplaces = n; +} + +//------------------------------------------------------------------------------ +// It set the number of continuous places in the model +//------------------------------------------------------------------------------ +void BPN::NumberOfContinuousPlaces(const int n) +{ + numberofcontinuousplaces = n; +} + +//------------------------------------------------------------------------------ +// It set the number of batch places in the model +//------------------------------------------------------------------------------ +void BPN::NumberOfBatchPlaces(const int n) +{ + numberofbatchplaces = n; +} + +//------------------------------------------------------------------------------ +// It set the number of triangular batch places in the model +//------------------------------------------------------------------------------ +void BPN::NumberOfTriangularBatchPlaces(const int n) +{ + numberoftriangularplaces = n; +} + +//------------------------------------------------------------------------------ +// It adds the new place to the model in the position pos +//------------------------------------------------------------------------------ +int BPN::AddPlace(int pos, Place *p) +{ + if (places[pos] != NULL) + return (1); + places[pos] = p; + return (0); +} + +//------------------------------------------------------------------------------ +// It set the initial marking of a discrete place in the position pos to m +//------------------------------------------------------------------------------ +void BPN::SetInitialMarking(int pos, int m) +{ + places[pos]->SetInitialMarking(m); +} + +//------------------------------------------------------------------------------ +// It set the steady marking of a discrete place in the position pos to m +//------------------------------------------------------------------------------ +void BPN::SetSteadyMarking(int pos, int m) +{ + places[pos]->SetSteadyMarking(m); +} + +//------------------------------------------------------------------------------ +// It set the initial marking of a continuous place in the position pos to m +//------------------------------------------------------------------------------ +void BPN::SetInitialMarking(int pos, double m) +{ + places[pos]->SetInitialMarking(m); +} + +//------------------------------------------------------------------------------ +// It set the steady marking of a continuous place in the position pos to m +//------------------------------------------------------------------------------ +void BPN::SetSteadyMarking(int pos, double m) +{ + places[pos]->SetSteadyMarking(m); +} + +//------------------------------------------------------------------------------ +// It set the initial marking of a batch place in the position pos to m +//------------------------------------------------------------------------------ +void BPN::AddBatchToInitialMarking(int pos, Batch &b) +{ + places[pos]->AddBatchToInitialMarking(b); +} + +//------------------------------------------------------------------------------ +// It set the steady marking of a batch place in the position pos to m +//------------------------------------------------------------------------------ +void BPN::AddBatchToSteadyMarking(int pos, Batch &b) +{ + places[pos]->AddBatchToSteadyMarking(b); +} + +//------------------------------------------------------------------------------ +// It set the initial marking of a batch place in the position pos to m +//------------------------------------------------------------------------------ +void BPN::AddTriangularToInitialMarking(int pos, ControllableBatch &b) +{ + places[pos]->AddBatchToInitialMarking(b); +} + +//------------------------------------------------------------------------------ +// It set the steady marking of a batch place in the position pos to m +//------------------------------------------------------------------------------ +void BPN::AddTriangularToSteadyMarking(int pos, ControllableBatch &b) +{ + places[pos]->AddBatchToSteadyMarking(b); +} + +//------------------------------------------------------------------------------ +// It adds an output arc from the place in position _place to the transition in +// in position _position with weight +//------------------------------------------------------------------------------ +int BPN::AddPlaceOutputArc(int _place, int _transition, double _weight) +{ + places[_place]->AddOutputArc(_transition, _weight); + transitions[_transition]->AddInputArc(_place, _weight); +} + +//------------------------------------------------------------------------------ +// It set the number of discrete transitions in the model +//------------------------------------------------------------------------------ +void BPN::NumberOfDiscreteTransitions(const int n) +{ + numberofdiscretetransitions = n; +} + +//------------------------------------------------------------------------------ +// It set the number of continuous transitions in the model +//------------------------------------------------------------------------------ +void BPN::NumberOfContinuousTransitions(const int n) +{ + numberofcontinuoustransitions = n; +} + +//------------------------------------------------------------------------------ +// It set the number of batch transitions in the model +//------------------------------------------------------------------------------ +void BPN::NumberOfBatchTransitions(const int n) +{ + numberofbatchtransitions = n; +} + +//------------------------------------------------------------------------------ +// It adds the new transition to the model in the position pos +//------------------------------------------------------------------------------ +int BPN::AddTransition(int pos, Transition *t) +{ + if (transitions[pos] != NULL) + return (1); + transitions[pos] = t; + return (0); +} + +//------------------------------------------------------------------------------ +// It adds an output arc from the place in position _place to the transition in +// in position _position with weight +//------------------------------------------------------------------------------ +int BPN::AddTransitionOutputArc(int _transition, int _place, double _weight) +{ transitions[_transition]->AddOutputArc(_place, _weight); + places[_place]->AddInputArc(_transition, _weight); +} + +//------------------------------------------------------------------------------ +// It verifies if the name is already used for another place/transition +//------------------------------------------------------------------------------ +int BPN::VerifyName(simuleau_name _name) +{ + for (int i=0; i<NumberOfPlaces(); i++){ + if (places[i] != NULL){ + if (!strcmp(places[i]->GetName(),_name)) + return (1); + } + } + for (int i=0; i<NumberOfTransitions(); i++){ + if (transitions[i] != NULL){ + if (!strcmp(transitions[i]->GetName(),_name)) + return (1); + } + } + return (0); +} + +//------------------------------------------------------------------------------ +// It returns the bpn model name +//------------------------------------------------------------------------------ +char* BPN::GetName() +{ + return (bpnname); +} + +//------------------------------------------------------------------------------ +// It returns the addresse of the node name +//------------------------------------------------------------------------------ +Node* BPN::GetNode(simuleau_name _name) +{ + for (int i=0; i<NumberOfPlaces(); i++){ + if (places[i] != NULL){ + if (!strcmp(places[i]->GetName(),_name)) + return (places[i]); + } + } + for (int i=0; i<NumberOfTransitions(); i++){ + if (transitions[i] != NULL){ + if (!strcmp(transitions[i]->GetName(),_name)) + return (transitions[i]); + } + } + return (NULL); +} +//------------------------------------------------------------------------------ +// It returns the number of discrete places in the model +//------------------------------------------------------------------------------ +int BPN::NumberOfDiscretePlaces() +{ + return (numberofdiscreteplaces); +} + +//------------------------------------------------------------------------------ +// It returns the number of continuous places in the model +//------------------------------------------------------------------------------ +int BPN::NumberOfContinuousPlaces() +{ + return (numberofcontinuousplaces); +} + +//------------------------------------------------------------------------------ +// It returns the number of batch places in the model +//------------------------------------------------------------------------------ +int BPN::NumberOfBatchPlaces() +{ + return (numberofbatchplaces); +} + +//------------------------------------------------------------------------------ +// It returns the number of triangular batch places in the model +//------------------------------------------------------------------------------ +int BPN::NumberOfTriangularBatchPlaces() +{ + return (numberoftriangularplaces); +} + +//------------------------------------------------------------------------------ +// It returns the number of all places in the model +//------------------------------------------------------------------------------ +int BPN::NumberOfPlaces() +{ + return (numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces + numberoftriangularplaces); +} + +//------------------------------------------------------------------------------ +// It returns the position of the place _name +//------------------------------------------------------------------------------ +int BPN::GetPlacePosition(simuleau_name _name) +{ + for (int i=0; i<NumberOfPlaces(); i++){ + if (places[i] != NULL){ + if (!strcmp(places[i]->GetName(),_name)) + return (i); + } + } + return (-1); +} + + +//------------------------------------------------------------------------------ +// It returns the name of the place in the position _place +//------------------------------------------------------------------------------ +char* BPN::GetPlaceName(place_id _place) +{ + return(places[_place]->GetName()); +} + +//------------------------------------------------------------------------------ +// It returns the pointer of the place in the position _place +//------------------------------------------------------------------------------ +Place* BPN::GetPlace(place_id _place) +{ + return(places[_place]); +} + +//------------------------------------------------------------------------------ +// It returns the place type +//------------------------------------------------------------------------------ +place_type BPN::GetPlaceType(simuleau_name _name) +{ + int j = 0; + int k = numberofdiscreteplaces; + for (int i=j; i<k; i++){ + if (places[i] != NULL){ + if (!strcmp(places[i]->GetName(),_name)) + return (Discrete_pl); + } + } + + j = k; + k += numberofcontinuousplaces; + for (int i=j; i<k; i++){ + if (places[i] != NULL){ + if (!strcmp(places[i]->GetName(),_name)) + return (Continuous_pl); + } + } + + j = k; + k += numberofbatchplaces; + for (int i=j; i<k; i++){ + if (places[i] != NULL){ + if (!strcmp(places[i]->GetName(),_name)) + return (Batch_pl); + } + } + + j = k; + k += numberoftriangularplaces; + for (int i=j; i<k; i++){ + if (places[i] != NULL){ + if (!strcmp(places[i]->GetName(),_name)) + return (Triangular_pl); + } + } +} + +//------------------------------------------------------------------------------ +// It returns the number of discrete transitions in the model +//------------------------------------------------------------------------------ +int BPN::NumberOfDiscreteTransitions() +{ + return (numberofdiscretetransitions); +} + +//------------------------------------------------------------------------------ +// It returns the number of continuous transitions in the model +//------------------------------------------------------------------------------ +int BPN::NumberOfContinuousTransitions() +{ + return (numberofcontinuoustransitions); +} + +//------------------------------------------------------------------------------ +// It returns the number of batch transitions in the model +//------------------------------------------------------------------------------ +int BPN::NumberOfBatchTransitions() +{ + return (numberofbatchtransitions); +} + + +//------------------------------------------------------------------------------ +// It returns the number of all transitions in the model +//------------------------------------------------------------------------------ +int BPN::NumberOfTransitions() +{ + return (numberofdiscretetransitions + numberofcontinuoustransitions + numberofbatchtransitions); +} + +//------------------------------------------------------------------------------ +// It returns the position of the transition _name +//------------------------------------------------------------------------------ +int BPN::GetTransitionPosition(simuleau_name _name) +{ + for (int i=0; i<NumberOfTransitions(); i++){ + if (transitions[i] != NULL){ + if (!strcmp(transitions[i]->GetName(),_name)) + return (i); + } + } + return (-1); +} + +//------------------------------------------------------------------------------ +// It returns the name of the transition in the position _trans +//------------------------------------------------------------------------------ +char* BPN::GetTransitionName(trans_id _trans) +{ + return(transitions[_trans]->GetName()); +} + +//------------------------------------------------------------------------------ +// It returns the pointer of the transition in the position _trans +//------------------------------------------------------------------------------ +Transition* BPN::GetTransition(trans_id _trans) +{ + return(transitions[_trans]); +} + + +//------------------------------------------------------------------------------ +// It returns the place type +//------------------------------------------------------------------------------ +trans_type BPN::GetTransitionType(simuleau_name _name) +{ + int j = 0; + int k = numberofdiscretetransitions; + for (int i=j; i<k; i++){ + if (transitions[i] != NULL){ + if (!strcmp(transitions[i]->GetName(),_name)) + return (Discrete_tr); + } + } + + j = k; + k += numberofcontinuoustransitions; + for (int i=j; i<k; i++){ + if (transitions[i] != NULL){ + if (!strcmp(transitions[i]->GetName(),_name)) + return (Continuous_tr); + } + } + + j = k; + k += numberofbatchtransitions; + for (int i=j; i<k; i++){ + if (transitions[i] != NULL){ + if (!strcmp(transitions[i]->GetName(),_name)) + return (Batch_tr); + } + } +} + +//------------------------------------------------------------------------------ +// It prints the bpn model +//------------------------------------------------------------------------------ +void BPN::Print(ostream &fout) +{ + fout << "BPN model name: " << bpnname << endl << endl; + + fout << "======" << endl; + fout << "Places" << endl; + fout << "======" << endl << endl; + + fout << "Number of places: " << (numberofdiscreteplaces + numberofcontinuousplaces + + numberofbatchplaces + numberoftriangularplaces) << endl; + fout << " Discrete places: " << numberofdiscreteplaces << endl; + fout << " Continuous places: " << numberofcontinuousplaces << endl; + fout << " Batch places: " << numberofbatchplaces << endl; + fout << " Triangular batch places: " << numberoftriangularplaces << endl << endl; + + fout << "Description of places " << endl; + fout << "=====================" << endl << endl; + + for (int i=0; i<NumberOfPlaces(); i++){ + places[i]->Print(fout); + } + + fout << "===========" << endl; + fout << "Transitions" << endl; + fout << "===========" << endl << endl; + + fout << "Number of transitions: " << (numberofdiscretetransitions + numberofcontinuoustransitions + + numberofbatchtransitions) << endl; + fout << " Discrete transitions: " << numberofdiscretetransitions << endl; + fout << " Continuous transitions: " << numberofcontinuoustransitions << endl; + fout << " Batch transitions: " << numberofbatchtransitions << endl << endl; + + fout << "Description of Transitions" << endl; + fout << "==========================" << endl << endl; + + for (int i=0; i<NumberOfTransitions(); i++){ + transitions[i]->Print(fout); + } +} + +//------------------------------------------------------------------------------ +// It writes place marks in the file +//------------------------------------------------------------------------------ +void BPN::WritePlaces(ostream &fout) +{ + for (int i=0; i<NumberOfPlaces(); i++){ + places[i]->Write(fout); + } +} + +//------------------------------------------------------------------------------ +// It writes continuous and batch transitions after to compute IFF +//------------------------------------------------------------------------------ +void BPN::WriteFlows(ostream &fout) +{ + for (int i=numberofdiscretetransitions; i<NumberOfTransitions(); i++){ + ((ContinuousTransition*)transitions[i])->Write(fout); + } +} + +//------------------------------------------------------------------------------ +// Compute new marks +//------------------------------------------------------------------------------ +void BPN::ComputeNewMarks(double duration) +{ + for (int i=0; i<NumberOfTransitions(); i++){ + transitions[i]->WalkThrough(duration); + } + + for (int i=0; i<NumberOfPlaces(); i++){ + places[i]->EvolveMarks(simulation->stime->GetPreviousDate()); + } +} + +//------------------------------------------------------------------------------ +// Reserve marks in discrete places +//------------------------------------------------------------------------------ +void BPN::ReserveMarks() +{ + for (int i=0; i<numberofdiscretetransitions; i++){ + if (transitions[i]->GetState() == 1.0){ + ((DiscreteTransition*)transitions[i])->SetEnabledDate(simulation->stime->GetCurrentDate()); + ((DiscreteTransition*)transitions[i])->ReserveMarksInputPlaces(); + } + } +} + +//------------------------------------------------------------------------------ +// Create batches in batch places with input flow non-zero +// TODO verify correct function call +//------------------------------------------------------------------------------ +void BPN::CreateBatches() +{ + int k = numberofdiscreteplaces + numberofcontinuousplaces; + + for (int i=k; i<NumberOfPlaces(); i++){ + switch (places[i]->IsA()){ + case Batch_pl : ((BatchPlace*)places[i])->CreateBatches(); + break; + case Triangular_pl: ((TriangularBatchPlace*)places[i])->CreateBatches(); + break; + } + } +} + +//------------------------------------------------------------------------------ +// Destruct batch into the batch places +//------------------------------------------------------------------------------ +void BPN::DestructBatches() +{ + int k = numberofdiscreteplaces + numberofcontinuousplaces; + + for (int i=k; i<NumberOfPlaces(); i++){ + ((BatchPlace*)places[i])->DestructBatches(); + } +} + +//------------------------------------------------------------------------------ +// Merge batches into the batch places +//------------------------------------------------------------------------------ +void BPN::MergeBatches() +{ + int k = numberofdiscreteplaces + numberofcontinuousplaces; + + for (int i=k; i<NumberOfPlaces(); i++){ + ((BatchPlace*)places[i])->MergeBatches(); + } +} + +//------------------------------------------------------------------------------ +// Compute the state of each transition +// TODO verify transitions +//------------------------------------------------------------------------------ +int BPN::ComputeTransitionsStates() +{ + + if( (NumberOfPlaces() == 0) && (NumberOfTransitions() == 0)){ + return 0; // No place or transition + } + + double p[NumberOfPlaces()]; + double t[NumberOfTransitions()]; + int steps = 0; + + for (int i=0; i<NumberOfPlaces(); i++){ + places[i]->SetState(0.0); + } + + for (int i=0; i<NumberOfTransitions(); i++){ + t[i] = transitions[i]->GetState(); + transitions[i]->SetPreviousState(t[i]); + transitions[i]->SetState(0.0); + } + + do{ + steps++; + + for (int i=0; i<NumberOfPlaces(); i++){ + p[i] = places[i]->GetState(); + places[i]->ComputeState(); + } + + for (int i=0; i<NumberOfTransitions(); i++){ + t[i] = transitions[i]->GetState(); + transitions[i]->ComputeState(); // to verify + } + + } while (StateStability(p,t) != 0); + + return (steps); +} + +//------------------------------------------------------------------------------ +// Verify the stabilty of the state of each place and transition +//------------------------------------------------------------------------------ +int BPN::StateStability(double *p, double *t) +{ + int result = 0; + + for (int i=0; i<NumberOfPlaces(); i++){ + if (p[i] != places[i]->GetState()) + result++; + } + + for (int i=0; i<NumberOfTransitions(); i++){ + if (t[i] != transitions[i]->GetState()) + result++; + } + return (result); +} + +//------------------------------------------------------------------------------ +// Compute batches behaviors +//------------------------------------------------------------------------------ +void BPN::ComputeBatchesBehaviours() +{ +// cout << "Compute batches behaviours\n"; + + int k = numberofdiscreteplaces + numberofcontinuousplaces; // only batch places + + for (int i=k; i<NumberOfPlaces(); i++){ + switch (places[i]->IsA()){ + case Batch_pl : ((BatchPlace*)places[i])->ComputeBehaviour(); + break; + case Triangular_pl: ((TriangularBatchPlace*)places[i])->ComputeBehaviour(); + break; + } + } +} + +//------------------------------------------------------------------------------ +// Merge batches into the batch places +//------------------------------------------------------------------------------ +void BPN::SetBehaviourFunctions() +{ + int k = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + + for (int i=k; i<NumberOfPlaces(); i++){ + ((TriangularBatchPlace*)places[i])->SetBehaviourFunctions(); + } +} + + +//------------------------------------------------------------------------------ +// Research structural conflit in the model +//------------------------------------------------------------------------------ +void BPN::ResearchStructuralConflict() +{ + for(int i=0; i<NumberOfPlaces(); i++){ + places[i]->ResearchStructuralConflict(); + } +} + +//------------------------------------------------------------------------------ +// Verify conflit in the model +// 0 - No conflit +// 1 - Conflit in discrete place +// 2 - Conflit in continuous place +//------------------------------------------------------------------------------ +int BPN::VerifyConflict() +{ +// cout << "Verifying conflicts\n"; + int conflict = 0; + + for(int i=0; i<NumberOfPlaces(); i++){ + if (places[i]->GetStructuralConflict()){ + conflict = places[i]->VerifyConflict(); + if (conflict) + return (conflict); + } + } + return (0); +} + +//------------------------------------------------------------------------------ +// It verifies if the net reaches the steady state +//------------------------------------------------------------------------------ +int BPN::IsSteadyStateReached() +{ + + for(int i=numberofdiscreteplaces; i<NumberOfPlaces(); i++){ + switch(places[i]->IsA()){ + case Continuous_pl : if (!((ContinuousPlace*)places[i])->IsSteadyMarkingReached()) + return 0; + break; + + case Batch_pl : if (!((BatchPlace*)places[i])->IsSteadyMarkingReached()) + return 0; + break; + } + } + + for(int i=numberofdiscretetransitions; i<NumberOfTransitions(); i++){ + if (!((ContinuousTransition*)transitions[i])->IsSteadyFlowReached()){ + return 0; + } + } + + return (1); +} + + + + +//------------------------------------------------------------------------------ +// Compute next event to Discrete Transition Fire type and put it in dtf list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventDTF(list<Event> * _dtf) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventDTF\n"; + + for(int i=0; i<numberofdiscretetransitions; i++){ + if (transitions[i]->GetState() != 0.0){ + eventdate = ((DiscreteTransition*)transitions[i])->GetTime() + ((DiscreteTransition*)transitions[i])->GetEnabledDate(); + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event DTF\n"; + Event *e = new Event(*transitions[i], eventdate, Discr_trans_fires); + _dtf->push_back(*e); + } + } + } +} + +//------------------------------------------------------------------------------ +// Compute next event to Continuous Place becomes Empty type and put it in cpe list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventCPE(list<Event> * _cpe) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventCPE\n"; + + int beginofcp = numberofdiscreteplaces; // start from the end of discrete places + int endofcp = numberofdiscreteplaces+numberofcontinuousplaces; // stop to the end of continuous places + + for (int i=beginofcp; i<endofcp; i++){ + if (places[i]->GetState() == 1){ + eventdate = ((ContinuousPlace*)places[i])->GetCPEEvent(); + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event CPE\n"; + Event *e = new Event(*places[i], eventdate, Cont_place_empty); + _cpe->push_back(*e); + } + } + } + +} + +//------------------------------------------------------------------------------ +// Compute next event to Discrete transistion becomes enabled type and put it in dte list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventDTE(list<Event> * _dte) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventDTE\n"; + + int beginofcp = numberofdiscreteplaces; // start from the end of discrete places + int endofcp = numberofdiscreteplaces+numberofcontinuousplaces; // stop to the end of continuous places + + for (int i=beginofcp; i<endofcp; i++){ + eventdate = ((ContinuousPlace*)places[i])->GetDTEEvent(); + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event DTE\n"; + Event *e = new Event(*places[i], eventdate, Discr_trans_enabled); + _dte->push_back(*e); + } + } +} + +//------------------------------------------------------------------------------ +// Compute next event to BOB type and put it in bob list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventBOB(list<Event> * _bob) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventBOB\n"; + + int beginofbp = numberofdiscreteplaces+numberofcontinuousplaces; // start from the end of continuous places + int endofbp = NumberOfPlaces(); // stop to the end of all places + + for (int i=beginofbp; i<endofbp; i++){ + switch(places[i]->IsA()){ + case Batch_pl : eventdate = ((BatchPlace*)places[i])->GetBOBEvent(); + break; + case Triangular_pl : eventdate = ((TriangularBatchPlace*)places[i])->GetBOBEvent(); + break; + } + + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event BOB\n"; + Event *e = new Event(*places[i], eventdate, Becomes_output_batch); + _bob->push_back(*e); + } + } +} + +//------------------------------------------------------------------------------ +// Compute next event to DOB type and put it in dob list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventDOB(list<Event> * _dob) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventDOB\n"; + + int beginofbp = numberofdiscreteplaces+numberofcontinuousplaces; // start from the end of continuous places + int endofbp = NumberOfPlaces(); // stop to the end of all places + + for (int i=beginofbp; i<endofbp; i++){ + switch(places[i]->IsA()){ + case Batch_pl : eventdate = ((BatchPlace*)places[i])->GetDOBEvent(); + break; + case Triangular_pl : eventdate = ((TriangularBatchPlace*)places[i])->GetDOBEvent(); + break; + } + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event DOB\n"; + Event *e = new Event(*places[i], eventdate, Destr_output_batch); + _dob->push_back(*e); + } + } +} + +//------------------------------------------------------------------------------ +// Compute next event to BBD type and put it in dtf list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventBBD(list<Event> * _bbd) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventBBD\n"; + + int beginofbp = numberofdiscreteplaces+numberofcontinuousplaces; // start from the end of continuous places + int endofbp = NumberOfPlaces(); // stop to the end of all places + + for (int i=beginofbp; i<endofbp; i++){ + switch(places[i]->IsA()){ + case Batch_pl : eventdate = ((BatchPlace*)places[i])->GetBBDEvent(); + break; + case Triangular_pl : eventdate = ((TriangularBatchPlace*)places[i])->GetBBDEvent(); + break; + } + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event BBD\n"; + Event *e = new Event(*places[i], eventdate, Batch_becomes_dense); + _bbd->push_back(*e); + } + } +} + +//------------------------------------------------------------------------------ +// Compute next event to TBM type and put it in tbm list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventTBM(list<Event> * _tbm) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventTBM\n"; + + int beginofbp = numberofdiscreteplaces+numberofcontinuousplaces; // start from the end of continuous places + int endofbp = NumberOfPlaces(); // stop to the end of all places + + for (int i=beginofbp; i<endofbp; i++){ + switch(places[i]->IsA()){ + case Batch_pl : eventdate = ((BatchPlace*)places[i])->GetTBMEvent(); + break; + case Triangular_pl : eventdate = ((TriangularBatchPlace*)places[i])->GetTBMEvent(); + break; + } + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event TBM\n"; + Event *e = new Event(*places[i], eventdate, Two_batches_meet); + _tbm->push_back(*e); + } + } +} + +//------------------------------------------------------------------------------ +// Compute next event to BMOB type and put it in bmob list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventBMOB(list<Event> * _bmob) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventBMOB\n"; + + int beginoftbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; // start from the end of batch places + int endoftbp = NumberOfPlaces(); // stop to the end of all places + + for (int i=beginoftbp; i<endoftbp; i++){ + eventdate = ((TriangularBatchPlace*)places[i])->GetBMOBEvent(); + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event BMOB\n"; + Event *e = new Event(*places[i], eventdate, Batch_meets_output_batch); + _bmob->push_back(*e); + } + } +} + +//------------------------------------------------------------------------------ +// Compute next event to OBD (outpu batch decongestion) type and put it in obd list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventOBD(list<Event> * _obd) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventOBD\n"; + + int beginoftbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; // start from the end of batch places + int endoftbp = NumberOfPlaces(); // stop to the end of all places + + for (int i=beginoftbp; i<endoftbp; i++){ + eventdate = ((TriangularBatchPlace*)places[i])->GetOBDEvent(); + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event OBD\n"; + Event *e = new Event(*places[i], eventdate, Output_batch_decongestion); + _obd->push_back(*e); + } + } +} + +//------------------------------------------------------------------------------ +// Compute next event to BD type and put it in bd list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventBD(list<Event> * _bd) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventBD\n"; + + int beginoftbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; // start from the end of batch places + int endoftbp = NumberOfPlaces(); // stop to the end of all places + + for (int i=beginoftbp; i<endoftbp; i++){ + eventdate = ((TriangularBatchPlace*)places[i])->GetBDEvent(); + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event BD\n"; + Event *e = new Event(*places[i], eventdate, Batch_decongestion); + _bd->push_back(*e); + } + } +} + +//------------------------------------------------------------------------------ +// Compute next event to BBF type and put it in bbf list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventBBF(list<Event> * _bbf) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventBBF\n"; + + int beginoftbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; // start from the end of batch places + int endoftbp = NumberOfPlaces(); // stop to the end of all places + + for (int i=beginoftbp; i<endoftbp; i++){ + eventdate = ((TriangularBatchPlace*)places[i])->GetBBFEvent(); + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event BBF\n"; + Event *e = new Event(*places[i], eventdate, Batch_becomes_free); + _bbf->push_back(*e); + } + } +} + +//=============================Onoff======CFF====================================== +//------------------------------------------------------------------------------ +// Compute next event to Place reaches steadying marking quantity and put it in psq list +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventPSQ(list<Event> * _psq) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventPSQ\n"; + + int beginofcbp = numberofdiscreteplaces; // start from the end of discrete places + int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; // stop at the end of batch places + + for (int i=beginofcbp; i<endofcbp; i++){ + switch (places[i] ->IsA()){ + case Continuous_pl: eventdate = ((ContinuousPlace*)places[i])->GetPSQEvent(); // + break; + case Batch_pl:eventdate = ((BatchPlace*)places[i])->GetPSQEvent(); // + break; + } + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event PSQ\n"; + Event *e = new Event(*places[i], eventdate, Place_steady_quan); // + _psq->push_back(*e); + } + } +} + +//=============================MCFF======event=======RBF=============================== +//------------------------------------------------------------------------------ +// Compute next event that the firing quantity satisfies the remaining marking quantity +// becomes free steady marking quantity of its output place and put it in rbf list +// + +// q_{i,j}^{r,s} = Post(p_i,t_j)(z_j^s - z_j(m)) <= q_i^{f,s} +//------------------------------------------------------------------------------ +void BPN::ComputeNextEventRBF(list<Event> * _rbf) +{ + double eventdate = 0.0; + + cout << "ComputeNextEventRBF\n"; + + + int beginofcbt = numberofdiscretetransitions; // start from the end of discrete transitions + int endofcbt = numberofdiscretetransitions + numberofcontinuoustransitions + numberofbatchtransitions; // stop at the end of batch transitions + + for (int i=beginofcbt; i<endofcbt; i++){ + switch(transitions[i]->IsA()){ + case Discrete_tr: + case Continuous_tr: eventdate = ((ContinuousTransition*)transitions[i])->GetRBFEvent(); + break; + case Batch_tr: eventdate = ((BatchTransition*)transitions[i])->GetRBFEvent(); + break; + + } + if ((eventdate - simulation->stime->GetCurrentDate()) >= PRF::prf.Min_Err_Date()){ + cout << "adding event RBF\n"; + Event *e = new Event(*transitions[i], eventdate, Remaining_becomes_freesteadyquan); // + _rbf->push_back(*e); + } + } +} + +//------------------------------------------------------------------------------ +// Compute Instantaneous Firing Flow (IFF) +//------------------------------------------------------------------------------ +void BPN::ComputeIFF() +{ + cout << "\nCompute IFF\n\n"; + + Flow *f; + double maxflow; + + // contraints a and b + int beginofcbt = numberofdiscretetransitions; + int endofcbt = NumberOfTransitions(); + + int numberofcontandbatchtransitions = numberofcontinuoustransitions + numberofbatchtransitions; + int numberofnotenabledcontandbatchtransitions = 0; + for (int i=beginofcbt; i<endofcbt; i++){ + if (transitions[i]->GetState() == 0.0){ + numberofnotenabledcontandbatchtransitions++; + } + } + + if (numberofcontandbatchtransitions == 0) // no need to compute IFF + return; + + // contraint c empty continuous place set + int beginofcp = numberofdiscreteplaces; + int endofcp = numberofdiscreteplaces + numberofcontinuousplaces; + int numberofemptycontinuousplaces = 0; + for (int i=beginofcp; i<endofcp; i++){ + if (((ContinuousPlace*)places[i])->GetMarks() == 0.0){ +// cout << "Empty place[" << i << "] : " << ((ContinuousPlace*)places[i])->GetMarks() << endl; + numberofemptycontinuousplaces++; + } + } + + // contraint d full batch place set + int beginofbp = numberofdiscreteplaces + numberofcontinuousplaces; + int endofbp = NumberOfPlaces(); + int numberoffullbatchplaces = 0; + for (int i=beginofbp; i<endofbp; i++){ + if (((BatchPlace*)places[i])->IsFull() == 1){ + numberoffullbatchplaces++; + } + } + + // contraints e, f + int numberofallbatchplaces = numberofbatchplaces + numberoftriangularplaces; + + // contraint g + int beginoftbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int endoftbp = NumberOfPlaces(); + + + int nc = 0; // total of contraints + int r = 0; // current contraint + char rname[256]; // row name + + double V[NumberOfTransitions()]; // used to compute the incidence matrix, only continuous and batch positions are used + + + // variables to the linear program + glp_prob *lp; + double IFF[numberofcontandbatchtransitions]; // to store the result of the linear program + + nc = numberofcontandbatchtransitions; // contraint a + nc+= numberofnotenabledcontandbatchtransitions; // contraint b + nc+= numberofemptycontinuousplaces; // contraint c + nc+= numberoffullbatchplaces; // contraint d + nc+= (numberofallbatchplaces * 2); // contraints e and f + nc+= numberoftriangularplaces; // contraints g + + // contraints matrix + int ia[nc * numberofcontandbatchtransitions]; + int ja[nc * numberofcontandbatchtransitions]; + double ar[nc * numberofcontandbatchtransitions]; + int arindex; + + + // initialising linear program + lp = glp_create_prob(); + glp_set_prob_name(lp, "IFF"); + glp_set_obj_dir(lp, GLP_MAX); + glp_add_cols(lp, numberofcontandbatchtransitions); + glp_add_rows(lp, nc); + + // initialising transitions bound +// cout << "\nTransitions bound\n\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + glp_set_obj_coef(lp, i, 1.0); // weigth of each transition + glp_set_col_name(lp, i, transitions[k]->GetName()); // name of the transition + f = transitions[k]->GetFlow(); + if (f->GetMaximumFlow() != 0.0) + glp_set_col_bnds(lp, i, GLP_DB, 0.0, f->GetMaximumFlow()); + else + glp_set_col_bnds(lp, i, GLP_FX, 0.0, 0.0); + +// cout << transitions[k]->GetName() << " : 0.0 - " << f->GetMaximumFlow() << endl; + } + + r = 1; + arindex = 1; + +// cout << "\nStart contraints\n\n"; + // constraint a +// cout << "Contraint a\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + sprintf(rname, "a.%d", i); + f = transitions[k]->GetFlow(); + glp_set_row_name(lp, r, rname); + if (f->GetMaximumFlow() != 0.0) + glp_set_row_bnds(lp, r, GLP_DB, 0.0, f->GetMaximumFlow()); + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weigth + arindex++; + r++; + +// cout << rname << " : " << "0.0 <= x <= " << f->GetMaximumFlow() << endl; + } + + // constraint b +// cout << "Contraint b\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + sprintf(rname, "b.%d", i); + if (transitions[k]->GetState() == 0.0){ + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weigth + arindex++; + r++; +// cout << rname << " : " << ja[arindex-1] << ": 0.0 = x = 0.0 " << endl; + } + } + + // constraint c +// cout << "Contraint c\n"; + for (int i=1, k=beginofcp; k<endofcp; k++, i++) { + sprintf(rname, "c.%d", i); + if (((ContinuousPlace*)places[k])->GetMarks() == 0.0){ + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_LO, 0.0, 0.0); + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); +// cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ +// cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } +// cout << endl; +// cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; +// cout << j << "(" << V[l] << ") - "; + } + } +// cout << " >= 0.0" << endl; + r++; + } + } + + + // constraint d +// cout << "Contraint d\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + sprintf(rname, "d.%d", i); + if (((BatchPlace *)places[k])->IsFull() == 1.0){ + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, 0.0); + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + V[j] += places[k]->GetWeightOfInputArc(j); + } + } +// cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; +// cout << j << "(" << V[l] << ") - "; + } + } +// cout << " <= 0.0" << endl; + r++; + } + } + + // constraint e +// cout << "Contraint e\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + switch (places[k]->IsA()){ + case Batch_pl: maxflow = ((BatchPlace*)places[k])->GetInstantaneousSpeed() * ((BatchPlace*)places[k])->GetDensity(); + break; + case Triangular_pl: maxflow = ((TriangularBatchPlace*)places[k])->GetInstantaneousSpeed() * ((TriangularBatchPlace*)places[k])->GetCriticalDensity(); + break; + } + sprintf(rname, "e.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxflow); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfInputArc(j); + } + } +// cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; +// cout << j << "(" << V[l] << ") - "; + } + } +// cout << "0.0 - " << maxflow << endl; + r++; + } + + + // constraint f +// cout << "Contraint f\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + maxflow = ((BatchPlace*)places[k])->GetInstantaneousSpeed() * ((BatchPlace*)places[k])->GetDensityOutputBatch(); + sprintf(rname, "f.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxflow); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfOutputArc(j); + } + } +// cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; +// cout << j << "(" << V[l] << ") - "; + } + } +// cout << "0.0 - " << maxflow << endl; + r++; + } + + // constraint g +// cout << "Contraint g\n"; + for (int i=1, k=beginoftbp; k<endoftbp; k++, i++) { + maxflow = ((TriangularBatchPlace*)places[k])->GetInstantaneousSpeed() * ((TriangularBatchPlace*)places[k])->GetCriticalDensity(); + sprintf(rname, "g.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxflow); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfOutputArc(j); + } + } +// cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; +// cout << j << "(" << V[l] << ") - "; + } + } +// cout << "0.0 - " << maxflow << endl; + r++; + } + + glp_term_out(GLP_OFF); + glp_load_matrix(lp, arindex-1, ia, ja, ar); + glp_simplex(lp, NULL); + + for (int i=0, k=beginofcbt; k<endofcbt; k++, i++) { + IFF[i] = glp_get_col_prim(lp, (i+1)); + f = ((ContinuousTransition*)transitions[k])->GetFlow(); + f->SetTheoreticalFlow(IFF[i]); + f->SetCurrentFlow(IFF[i]); + +// cout << transitions[k]->GetName() << " : " << IFF[i] << endl; + } + + int col[numberofcontandbatchtransitions]; + double val[numberofcontandbatchtransitions]; + +/* for (int i=1; i<=glp_get_num_rows(lp); i++){ + cout << glp_get_row_name(lp, i) << " : "; + for (int j=1; j<=glp_get_mat_row(lp, i, col, val); j++){ + cout << col[j] << "(" << val[j] << ") - "; + } + cout << glp_get_row_lb(lp, i) << " - " << glp_get_row_ub(lp, i) << endl; + } +*/ + glp_delete_prob(lp); +} + +//------------------------------------------------------------------------------ +// Compute Controlled Firing Flow (CFF) based on steady flow +//------------------------------------------------------------------------------ +void BPN::ComputeCFF() +{ + cout << "\nCompute CFF\n\n"; + + Flow *u; + double steadyflow; + double maxflow; + + + // Verify if the marking is reached in this procedure + + + + // contraints a and b ==> not enabled transition set + int beginofcbt = numberofdiscretetransitions; + int endofcbt = numberofdiscretetransitions + numberofcontinuoustransitions + numberofbatchtransitions; + + int numberofcontandbatchtransitions = numberofcontinuoustransitions + numberofbatchtransitions; + int numberofnotenabledcontandbatchtransitions = 0; + int numberofnotenabledorlesssteadcontandbatchtransitions = 0; + for (int i=beginofcbt; i<endofcbt; i++){ + if (transitions[i]->GetState() == 0.0 ){ + numberofnotenabledcontandbatchtransitions++; + } + + if ((transitions[i]->GetState() == 0.0) || (transitions[i]->IsOnState() == 0)){ + numberofnotenabledorlesssteadcontandbatchtransitions++; + } + } + + if (numberofcontandbatchtransitions == 0) // no need to compute CFF + return; + + // contraint c ===>continuous and batch place whose marking quantity is greater than steady marking quantity + int beginofcbp = numberofdiscreteplaces; + int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberofgreatercontandbatchplaces = 0; + for (int i=beginofcbp; i<endofcbp; i++){ + switch (places[i] ->IsA()){ + case Continuous_pl: if (((ContinuousPlace*)places[i])->IsGreaterThanSteadyQuantity() == 1){ + numberofgreatercontandbatchplaces++; + } + break; + case Batch_pl: if (((BatchPlace*)places[i])->IsGreaterThanSteadyQuantity() == 1){ + numberofgreatercontandbatchplaces++; + } + break; + + } + } + + // contraint d ===>continuous and batch place whose marking quantity is equal to steady marking quantity (S_E) + // int beginofcbp = numberofdiscreteplaces; + // int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberofequalcontandbatchplaces = 0; + for (int i=beginofcbp; i<endofcbp; i++){ + switch (places[i] ->IsA()){ + case Continuous_pl: if (((ContinuousPlace*)places[i])->IsEqualSteadyQuantity() == 1){ + numberofequalcontandbatchplaces++; + } + break; + case Batch_pl: if (((BatchPlace*)places[i])->IsEqualSteadyQuantity() == 1){ + numberofequalcontandbatchplaces++; + } + break; + } + } + + + // contraint e ===>continuous and batch place whose marking quantity is less than steady marking quantity(S_L) + int beginofbp = numberofdiscreteplaces + numberofcontinuousplaces; + int endofbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberoflesscontandbatchplaces = 0; + for (int i=beginofcbp; i<endofcbp; i++){ + switch (places[i] ->IsA()){ + case Continuous_pl: if (((ContinuousPlace*)places[i])->IsLessThanSteadyQuantity() == 1){ + numberoflesscontandbatchplaces++; + } + break; + case Batch_pl: if (((BatchPlace*)places[i])->IsLessThanSteadyQuantity() == 1){ + numberoflesscontandbatchplaces++; + } + break; + } + } + +// contraint f ===>transition with at least one of its input places belonging to S_L. +// int beginofcbt = numberofdiscretetransitions; + // int endofcbt = numberofdiscretetransitions + numberofcontinuoustransitions + numberofbatchtransitions; +// int numberofcontandbatchtransitions = numberofcontinuoustransitions + numberofbatchtransitions; + int numberofinputplacelesscontandbatchtransitions = 0; + for (int i=beginofcbt; i<endofcbt; i++){ + switch (transitions[i] ->IsA()){ + case Continuous_tr: if (((ContinuousTransition*)transitions[i])->GetState()==0.0){ //GetCFFState()= 0.0 + numberofinputplacelesscontandbatchtransitions++; + break; + } + case Batch_tr: if (((BatchTransition*)transitions[i])->GetState()== 0.0){ + numberofinputplacelesscontandbatchtransitions++; + } + break; + } +} +//constraint g + // int numberofbatchplaces; + + + + + int nc = 0; // total of contraints + int r = 0; // current contraint + char rname[256]; // row name + + double V[NumberOfTransitions()]; // used to compute the incidence matrix, only continuous and batch positions are used + + + // variables to the linear program + glp_prob *lp; + double CFF[numberofcontandbatchtransitions]; // to store the result of the linear program + + nc = numberofcontandbatchtransitions; // contraint a + nc+= numberofnotenabledorlesssteadcontandbatchtransitions; // contraint b + nc+= numberofgreatercontandbatchplaces; // contraint c + nc+= numberofequalcontandbatchplaces; // contraint d + //nc+= numberoflesscontandbatchplaces; // contraint e + //nc+= numberofinputplacelesscontandbatchtransitions; // contraint f + nc+= numberofbatchplaces; // contraints g + + + // contraints matrix + int ia[nc * numberofcontandbatchtransitions]; + int ja[nc * numberofcontandbatchtransitions]; + double ar[nc * numberofcontandbatchtransitions]; + int arindex; + + + // initialising linear program + lp = glp_create_prob(); + glp_set_prob_name(lp, "CFF"); + glp_set_obj_dir(lp, GLP_MAX); + glp_add_cols(lp, numberofcontandbatchtransitions); + glp_add_rows(lp, nc); + + // initialising transitions bound + cout << "\nTransitions bound\n\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + glp_set_obj_coef(lp, i, 1.0); // set (change) objective coefficient or constant term + glp_set_col_name(lp, i, transitions[k]->GetName()); // name of the transition + u = transitions[k]->GetFlow(); + if (u->GetSteadyFlow() != 0.0) + glp_set_col_bnds(lp, i, GLP_DB, 0.0, u->GetSteadyFlow());//set (change) column bounds + else + glp_set_col_bnds(lp, i, GLP_FX, 0.0, 0.0); + + cout << transitions[k]->GetName() << " : 0.0 - " << u->GetSteadyFlow() << endl; + } + + r = 1; + arindex = 1; + + cout << "\nStart contraints\n\n"; + // constraint a + cout << "Contraint a\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + sprintf(rname, "a.%d", i); + u = transitions[k]->GetFlow(); + glp_set_row_name(lp, r, rname); + if (u->GetSteadyFlow() != 0.0) + glp_set_row_bnds(lp, r, GLP_DB, 0.0, u->GetSteadyFlow()); //compare with steadyflow + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weigth + arindex++; + r++; + + cout << rname << " : " << "0.0 <= x <= " << u->GetSteadyFlow() << endl; + } + + // constraint b + cout << "Contraint b\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + sprintf(rname, "b.%d", i); + if (transitions[k]->GetState() == 0.0 || (transitions[k]->IsOnState() == 0)){ + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weigth + arindex++; + r++; + cout << rname << " : " << ja[arindex-1] << ": 0.0 = x = 0.0 " << endl; + } + } + + // constraint c + cout << "Contraint c\n"; + for (int i=1, k=beginofcbp; k<endofcbp; k++, i++) { + switch (places[k] ->IsA()){ + case Continuous_pl: if (((ContinuousPlace*)places[k])->IsGreaterThanSteadyQuantity() == 0) + continue; + break; + case Batch_pl: if (((BatchPlace*)places[k])->IsGreaterThanSteadyQuantity() == 0) + continue; + break; + } + sprintf(rname, "c.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, 0.0); //look after + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } + cout << endl; + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << " <= 0.0" << endl; + r++; + } + + //constraint d + cout << "Contraint d\n"; + for (int i=1, k=beginofcbp; k<endofcbp; k++, i++) { + switch (places[k] ->IsA()){ + case Continuous_pl: if (((ContinuousPlace*)places[k])->IsEqualSteadyQuantity() == 0) + continue; + break; + case Batch_pl: if (((BatchPlace*)places[k])->IsEqualSteadyQuantity() == 0) + continue; + break; + } + sprintf(rname, "d.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } + cout << endl; + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << " = 0.0" << endl; + r++; + } + + // constraint d +// cout << "Contraint d\n"; + /* for (int i=1, k=beginofcbp; k<endofcbp; k++, i++) { + switch (places[k] ->IsA()){ + case Continuous_pl: if (((ContinuousPlace*)places[k])->IsEqualSteadyQuantity() == 1.0){ + } + break; + case Batch_pl: if (((BatchPlace*)places[k])->IsEqualSteadyQuantity() == 1.0){ + } + break; + } + sprintf(rname, "d.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, 0.0); + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + V[j] += places[k]->GetWeightOfInputArc(j); + } + } +// cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; +// cout << j << "(" << V[l] << ") - "; + } + } +// cout << " <= 0.0" << endl; + r++; + } +*/ + + // constraint e //input place's marking quantity is less than steady marking quantity. + cout << "Contraint e\n"; + + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + maxflow = ((BatchPlace*)places[k])->GetInstantaneousSpeed() * ((BatchPlace*)places[k])->GetDensityOutputBatch(); + sprintf(rname, "e.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxflow); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfOutputArc(j); + } + } + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << "0.0 <= x <= " << maxflow << endl; + r++; +} + + glp_term_out(GLP_OFF); + glp_load_matrix(lp, arindex-1, ia, ja, ar); + glp_simplex(lp, NULL); + + for (int i=0, k=beginofcbt; k<endofcbt; k++, i++) { + CFF[i] = glp_get_col_prim(lp, (i+1)); + u = ((ContinuousTransition*)transitions[k])->GetFlow(); + u->SetTheoreticalFlow(CFF[i]); + u->SetCurrentFlow(CFF[i]); + +// cout << transitions[k]->GetName() << " : " << CFF[i] << endl; + } + + + + int col[numberofcontandbatchtransitions]; + double val[numberofcontandbatchtransitions]; + +/* for (int i=1; i<=glp_get_num_rows(lp); i++){ + cout << glp_get_row_name(lp, i) << " : "; + for (int j=1; j<=glp_get_mat_row(lp, i, col, val); j++){ + cout << col[j] << "(" << val[j] << ") - "; + } + cout << glp_get_row_lb(lp, i) << " - " << glp_get_row_ub(lp, i) << endl; + } +*/ + glp_delete_prob(lp); +}//======================================================================= + + + +//--------------------------------------------------------------------------- +// Compute current firing quantity at each time step +//------------------------------------------------------------------------------- +void BPN::ComputeCurrentFiringQuantity(double steptime) +{ + FiringQuantity *z; + Flow *f; + double currentfiringquantity1; + + for (int i=0; i<NumberOfTransitions(); i++){ + f=transitions[i]->GetFlow(); + z=transitions[i]->GetFiringQuantity(); + // currentfiringquantity=transitions[i]->CurrentFiringQuantity(); + currentfiringquantity1 = (f->GetCurrentFlow() * steptime) + z->GetCurrentFiringQuantity(); + // cout<<"current first: "<<currentfiringquantity<<endl; + z->SetCurrentFiringQuantity(currentfiringquantity1); + // cout<<"current second: "<<currentfiringquantity<<endl; + // currentfiringquantity-= f->GetCurrentFlow() * steptime; + // cout<<"current third: "<<currentfiringquantity<<endl; + } +} + +//-------------------------------------------------------------------------- +// Compute steady firing quantity vector (minimal firing count vector) +//-------------------------------------------------------------------------- +// Solve the LLP: +// min Z^s +// q^s=q^0 + C * Z^s +// Z^s >= 0 +//-------------------------------------------------------------------------- +void BPN::ComputeSteadyFiringQuantity() +{ + Transition *t; + Place *p; + Flow *f; + FiringQuantity *z; + double steadyfiringquantity; + double remainingquantity; + + // contraints a + int beginofcbp = numberofdiscreteplaces; + int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberofcontandbatchplaces = numberofcontinuousplaces + numberofbatchplaces; + + //constraints b + int beginofcbt = numberofdiscretetransitions; + int endofcbt = numberofdiscretetransitions + numberofcontinuoustransitions + numberofbatchtransitions; + int numberofcontandbatchtransitions = numberofcontinuoustransitions + numberofbatchtransitions; + + + int nc = 0; // total of contraints + int r = 0; // current contraint + char rname[256]; // row name + + double V[NumberOfTransitions()]; // used to compute the incidence matrix, only continuous and batch positions are used + + + // variables to the linear program + glp_prob *lp; + double SS[numberofcontandbatchtransitions+1]; // to store the result of the linear program + //double *SS; + + nc = numberofcontandbatchplaces; // contraint a + nc+= numberofcontandbatchtransitions; // contraint b + + + // contraints matrix + int ia[nc * (numberofcontandbatchtransitions)]; + int ja[nc * (numberofcontandbatchtransitions)]; + double ar[nc * (numberofcontandbatchtransitions)]; + int arindex; + + // initialising linear program + lp = glp_create_prob(); + glp_set_prob_name(lp, "ZS"); + glp_set_obj_dir(lp, GLP_MAX); + glp_add_cols(lp, (numberofcontandbatchtransitions)); + glp_add_rows(lp, nc); + + + + cout << "\nSteady firing quantities bound\n\n"; + for (int k=beginofcbt; k<endofcbt; k++) { + glp_set_obj_coef(lp, k+1, -1.0); // set (change) objective coefficient or constant term + glp_set_col_name(lp, k+1, transitions[k]->GetName()); // name of the transition + f = transitions[k]->GetFlow(); + if (f->GetMaximumFlow() != 0.0) + glp_set_col_bnds(lp, k+1, GLP_LO, 0.0, 0.0);//set (change) column bounds + else + glp_set_col_bnds(lp, k+1, GLP_FX, 0.0, 0.0); + + cout << transitions[k]->GetName() << " z: >= " << 0.0 << endl; + } + + + + r = 1; + arindex = 1; + + + cout << "\nStart contraints\n\n"; + // constraint a + cout << "Contraint a\n"; + for (int i=1, k=beginofcbp; k<endofcbp; k++, i++) { + switch (places[k] ->IsA()){ + case Continuous_pl: + remainingquantity = ((ContinuousPlace*)places[k])->GetSteadyMarks()- ((ContinuousPlace*)places[k])->GetInitialMarks(); + break; + case Batch_pl: + remainingquantity = ((BatchPlace*)places[k])->GetSteadyQuantity()-((BatchPlace*)places[k])->GetInitialQuantity(); + + break; + } + + sprintf(rname, "a.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, remainingquantity, remainingquantity); + + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } + + cout << endl; + cout << rname << " : "; + for (int j=0, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[j] != 0.0){ + ia[arindex] = r; + ja[arindex] = l+1; + ar[arindex] = V[j]; + arindex++; + cout << "Zs"<< j << "(" << V[j] << ") + "; + } + } + cout << " = "<< remainingquantity << endl; + r++; + } + + + // constraint b + cout << "Contraint b\n"; + + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + sprintf(rname, "b.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_LO, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = k+1; + ar[arindex] = 1.0; // weight + arindex++; + r++; + cout << rname << " : " << "Zs " << i << " >= 0.0 " << endl; + } + + + glp_term_out(GLP_OFF); + glp_load_matrix(lp, arindex-1, ia, ja, ar); + glp_simplex(lp, NULL); + + + for (int i=1;i<(numberofcontandbatchtransitions+1); i++){ + SS[i]=glp_get_col_prim(lp, i); + cout<< "SS[" << i <<"] = " << SS[i]<<endl; + z=transitions[i-1]->GetFiringQuantity(); + z->SetSteadyFiringQuantity(SS[i]); + +// transitions[i]->SetSteadyFiringQuantity(SS[i]); + //steadyfiringquantity->SetSteadyFiringQuantity(SS[i]); + //SS = calloc(1+numberofcontandbatchplaces+2*numberofcontandbatchtransitions, sizeof(double)); + } + +// for (int i=1;i<(numberofcontandbatchtransitions+1); i++){ +// printf("z=%lf,SS[i]=%lf\n",z,i, SS[i]); +// } + + // f = ((ContinuousTransition*)transitions[k-numberofcontandbatchplaces])->GetFlow(); + // f->SetTheoreticalFlow(SS[k]); + // f->SetCurrentFlow(SS[k]); + + // cout << transitions[k-numberofcontandbatchplaces]->GetName() << " : " << SS[i] << endl; + + int col[numberofcontandbatchtransitions]; + double val[numberofcontandbatchtransitions]; + + /* + for (int i=1; i<=glp_get_num_rows(lp); i++){ + cout << glp_get_row_name(lp, i) << " : "; + for (int j=1; j<=glp_get_mat_row(lp, i, col, val); j++){ + cout << col[j] << "(" << val[j] << ") - "; + } + cout << glp_get_row_lb(lp, i) << " - " << glp_get_row_ub(lp, i) << endl; + } + */ + glp_delete_prob(lp); + return 0; +} + + +//============================================================================== +// Compute the steady state with assigned transfer speed +//============================================================================== +// To do list: +// 1. Set the result of marking and flow into steady marking and steady flow. +// 2. Give the computation of the steady state with variable transfer speed. +// 3. Consider the discrete nodes. +void BPN::ComputeSteadyState() +{ + + cout << "\nCompute Steadystate\n\n"; + + + double capacity; + double quantity_initial; + double maxflow; + Flow *f; + double z; + + + // contraints a + int beginofcbt = numberofbatchplaces+numberofcontinuousplaces+numberofdiscreteplaces+numberofdiscretetransitions; + int endofcbt = numberofbatchplaces+numberofcontinuousplaces+numberofdiscreteplaces+numberofdiscretetransitions + numberofcontinuoustransitions + numberofbatchtransitions; + int numberofcontandbatchtransitions = numberofcontinuoustransitions + numberofbatchtransitions; + + //constraints b and b' + int beginofbp = numberofdiscreteplaces + numberofcontinuousplaces; + int endofbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; +// int numberofbatchplaces; + + //constraints c + + //constraints d + int beginofcbp = numberofdiscreteplaces; + int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberofcontandbatchplaces = numberofcontinuousplaces + numberofbatchplaces; + + //constraints e + int beginofft = numberofcontandbatchplaces + numberofcontandbatchtransitions; + int endofft = numberofcontandbatchplaces + numberofcontandbatchtransitions + numberofcontandbatchtransitions; + + // set value to all places and transitions + // int numberofcontinuousplaces; + // int numberofcontinuoustransitions; + + // if (numberofcontandbatchtransitions == 0 || numberofcontandbatchplaces ==0) // no need to compute CFF + // return; + + + int nc = 0; // total of contraints + int r = 0; // current contraint + char rname[256]; // row name + + double V[NumberOfTransitions()]; // used to compute the incidence matrix, only continuous and batch positions are used + + + // variables to the linear program + glp_prob *lp; + double SS[numberofcontandbatchplaces+2*numberofcontandbatchtransitions+1]; // to store the result of the linear program + //double *SS; + + nc = numberofcontandbatchtransitions; // contraint a + nc+= numberofbatchplaces; // contraint b + nc+= numberofbatchplaces; // contraint b' + nc+= numberofbatchplaces; // contraint c + nc+= numberofcontandbatchplaces; // contraint d + nc+= numberofcontandbatchplaces; // contraint e + + + // contraints matrix + int ia[nc * (numberofcontandbatchplaces+2*numberofcontandbatchtransitions)]; + int ja[nc * (numberofcontandbatchplaces+2*numberofcontandbatchtransitions)]; + double ar[nc * (numberofcontandbatchplaces+2*numberofcontandbatchtransitions)]; + int arindex; + + // initialising linear program + lp = glp_create_prob(); + glp_set_prob_name(lp, "SS"); + glp_set_obj_dir(lp, GLP_MAX); + glp_add_cols(lp, (numberofcontandbatchplaces+2*numberofcontandbatchtransitions)); + glp_add_rows(lp, nc); + + + // initialising transitions bound + cout << "\nTransitions bound\n\n"; + + //wodes conflict example coefficient. + // glp_set_obj_coef(lp, 3, 1.0); + // glp_set_obj_coef(lp, 6, 10.0); + // glp_set_obj_coef(lp, 8, 20.0); + // glp_set_obj_coef(lp, 9, 1.0); + +//example1 one batch place + // glp_set_obj_coef(lp, 1, 1); + // glp_set_obj_coef(lp, 2, 10); + + // glp_set_obj_coef(lp, 3, 10.0); + // glp_set_obj_coef(lp, 4, 1.0); + + // glp_set_obj_coef(lp, 5, 1.0); + // glp_set_obj_coef(lp, 6, 10.0); + + // glp_set_obj_coef(lp, 11, 1.0); + + //example1 two batch place +// glp_set_obj_coef(lp, 1, 1.0); +// glp_set_obj_coef(lp, 3, 10.0); +// glp_set_obj_coef(lp, 2, 1.0); +// glp_set_obj_coef(lp, 4, 10.0); + +// glp_set_obj_coef(lp, 5, 10.0); +// glp_set_obj_coef(lp, 6, 1.0); +//glp_set_obj_coef(lp, 8, 1.0); +//glp_set_obj_coef(lp, 9, 10.0); + // glp_set_obj_coef(lp, 7, 1.0); + // glp_set_obj_coef(lp, 9, 1.0); +// glp_set_obj_coef(lp, 1, 1.0); +// glp_set_obj_coef(lp, 3, 10.0); +// glp_set_obj_coef(lp, 8, 1.0); +// glp_set_obj_coef(lp, 10, 3.0); + +//wodes+tz1+tz2 +//glp_set_obj_coef(lp, 10, 10.0); +//glp_set_obj_coef(lp, 11, 1.0); +//glp_set_obj_coef(lp, 4, 5.0); + + + + for (int k=beginofcbt; k<endofcbt; k++) { + glp_set_obj_coef(lp, k+1, 1.0); // set (change) objective coefficient or constant term + glp_set_col_name(lp, k+1, transitions[k-numberofcontandbatchplaces]->GetName()); // name of the transition + f = transitions[k-numberofcontandbatchplaces]->GetFlow(); + if (f->GetMaximumFlow() != 0.0) + glp_set_col_bnds(lp, k+1, GLP_DB, 0.0, f->GetMaximumFlow());//set (change) column bounds + else + glp_set_col_bnds(lp, k+1, GLP_FX, 0.0, 0.0); + + cout << transitions[k-numberofcontandbatchplaces]->GetName() << " : 0.0 - " << f->GetMaximumFlow() << endl; + } + + // initialising quantities bound + cout << "\nQuantities bound\n\n"; + for (int k=beginofcbp; k<endofcbp; k++) { + capacity = ((BatchPlace*)places[k])->GetDensity()*((BatchPlace*)places[k])->GetLength(); + // glp_set_obj_coef(lp, k+1, 0.0); // set (change) objective coefficient or constant term + glp_set_col_name(lp, k+1, places[k]->GetName()); // name of the transition + switch (places[k] ->IsA()){ + case Batch_pl: if (capacity != 0.0){ + glp_set_col_bnds(lp, k+1, GLP_DB, 0.0, capacity); + } + else{ + glp_set_col_bnds(lp, k+1, GLP_FX, 0.0, 0.0); + } + cout << places[k]->GetName() << " : 0.0 - " << capacity<<"\n"; + continue; + + break; + + case Continuous_pl: capacity = ((BatchPlace*)places[k+numberofcontinuousplaces])->GetDensity()*((BatchPlace*)places[k+numberofcontinuousplaces])->GetLength(); + glp_set_col_bnds(lp, k+1, GLP_DB, 0.0, capacity); //maybe revised! + cout << places[k]->GetName() << " : 0.0 - "<<capacity<<"\n"; + continue; + break; + } + } + + cout << "\nMinimal firing quantities bound\n\n"; + for (int k=beginofft; k<endofft; k++) { + // glp_set_obj_coef(lp, k+1, 1.0e-6); // set (change) objective coefficient or constant term + glp_set_col_name(lp, k+1, transitions[k-numberofcontandbatchplaces-numberofcontandbatchtransitions]->GetName()); // name of the transition + f = transitions[k-numberofcontandbatchplaces-numberofcontandbatchtransitions]->GetFlow(); + if (f->GetMaximumFlow() != 0.0) + glp_set_col_bnds(lp, k+1, GLP_LO, 0.0, 0.0);//set (change) column bounds + else + glp_set_col_bnds(lp, k+1, GLP_FX, 0.0, 0.0); + + cout << transitions[k-numberofcontandbatchplaces-numberofcontandbatchtransitions]->GetName() << " z: >= " << 0.0 << endl; + } + + r = 1; + arindex = 1; + + + cout << "\nStart contraints\n\n"; + // constraint a + cout << "Contraint a\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + sprintf(rname, "a.%d", i); + f = transitions[k-numberofcontandbatchplaces]->GetFlow(); + glp_set_row_name(lp, r, rname); + if (f->GetMaximumFlow() != 0.0) + glp_set_row_bnds(lp, r, GLP_DB, 0.0, f->GetMaximumFlow()); //compare with steadyflow + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = k+1; + ar[arindex] = 1.0; // weigth + arindex++; + r++; + cout << rname << " : " << "0.0 <= y <= " << f->GetMaximumFlow() << endl; + } + + // constraint b + cout << "Contraint b\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + sprintf(rname, "b.%d", i); + capacity= ((BatchPlace*)places[k])->GetDensity() * ((BatchPlace*)places[k])->GetLength(); + glp_set_row_name(lp, r, rname); + if (capacity != 0.0 ){ + glp_set_row_bnds(lp, r, GLP_DB, 0.0, capacity); + } + else{ + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + } + ia[arindex] = r; + ja[arindex] = k+1; + ar[arindex] = 1.0; // weigth + arindex++; + r++; + cout << rname << " : " << " 0.0 <= "<< " q" <<ja[arindex-1] << " <= "<<capacity << endl; + } + + // constraint b' + cout << "Contraint b\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + sprintf(rname, "b.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_LO, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = k+1; + ar[arindex] = 1.0 ; + arindex++; + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfOutputArc(j); + } + } + cout << rname << " : " << "q" <<k+1; + + + for (int j=0, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[j] != 0.0){ + ia[arindex] = r; + ja[arindex] = l+1; + ar[arindex] = -V[j] * ((BatchPlace*)places[k])->GetLength() / ((BatchPlace*)places[k])->GetInstantaneousSpeed() ; + arindex++; + cout << ar[arindex-1]<<"y * " <<j+1; + } + } + cout << ">=0.0" <<endl; + r++; +} + + // Contraint c + cout << "Contraint c\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + maxflow = ((BatchPlace*)places[k])->GetInstantaneousSpeed() * ((BatchPlace*)places[k])->GetDensity(); + + sprintf(rname, "c.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxflow); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfInputArc(j); + } + } + cout << rname << " : "; + for (int j=0, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[j] != 0.0){ + ia[arindex] = r; + ja[arindex] = l+1; + ar[arindex] = V[j]; + arindex++; + cout << "y"<<j+1 << "(" << V[j] << ") + "; + } + } + cout << "<=" << maxflow << endl; + r++; + } + + // constraint d + + cout << "Contraint d\n"; + + for (int i=1, k=beginofcbp; k<endofcbp; k++, i++) { + + sprintf(rname, "d.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); //look after + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + cout << rname<< ":"; + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + // cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + // cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + cout << "y"<<j+1 << "(" << V[j] << ") + "; + } + + for (int j=0, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[j] != 0.0){ + ia[arindex] = r; + ja[arindex] = l+1; + ar[arindex] = V[j]; + arindex++; + + } + } + cout << " = 0.0" << endl; + r++; + } + + + //constraint e + cout << "Contraint e\n"; + for (int i=1, k=beginofcbp; k<endofcbp; k++, i++) { + switch (places[k] ->IsA()){ + case Continuous_pl: quantity_initial =((ContinuousPlace*)places[k])->GetMarks(); + break; + case Batch_pl:quantity_initial= ((BatchPlace*)places[k])->GetInitialQuantity(); + break; + } + sprintf(rname, "e.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, quantity_initial, quantity_initial); + + ia[arindex] = r; + ja[arindex] = k+1; + ar[arindex] = 1.0; // weight + arindex++; + cout << rname<< " : "<<"q"<<k+1; + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + // cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + // cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + cout << "+z"<<j+1 << "(" << V[j] << ") "; + } + + for (int j=0, l=beginofft; l<endofft; j++, l++) { + if (V[j] != 0.0){ + ia[arindex] = r; + ja[arindex] = l+1; + ar[arindex] = -V[j]; + arindex++; + // cout << j << "(" << V[j] << ") - "; + } + } + cout << "=" <<quantity_initial<< endl; + r++; + } + + + glp_term_out(GLP_OFF); + glp_load_matrix(lp, arindex-1, ia, ja, ar); + glp_simplex(lp, NULL); + + cout<<"\nThe steady state is : "<<endl; + z = glp_get_obj_val(lp); + + + + for (int i=1;i<(numberofcontandbatchplaces+2*numberofcontandbatchtransitions+1); i++){ + SS[i]=glp_get_col_prim(lp, i); + //SS = calloc(1+numberofcontandbatchplaces+2*numberofcontandbatchtransitions, sizeof(double)); + } + + for (int i=1;i<(numberofcontandbatchplaces+2*numberofcontandbatchtransitions+1); i++){ + printf("z=%lf,SS[i]=%lf\n",z,i, SS[i]); + // if (i< (numberofcontandbatchplaces+1)){ + +// if (i< (numberofcontandbatchplaces+numberofcontinuoustransitions+1 && i > numberofcontandbatchplaces)){ +// f = ((ContinuousTransition*)transitions[i+numberofcontandbatchplaces-1])->GetFlow(); +// f->SetTheoreticalFlow(SS[i+numberofcontandbatchplaces]); +// f->SetCurrentFlow(SS[i+numberofcontandbatchplaces]); +// } + } + + // f = ((ContinuousTransition*)transitions[k-numberofcontandbatchplaces])->GetFlow(); + // f->SetTheoreticalFlow(SS[k]); + // f->SetCurrentFlow(SS[k]); + + // cout << transitions[k-numberofcontandbatchplaces]->GetName() << " : " << SS[i] << endl; + + int col[numberofcontandbatchplaces+2*numberofcontandbatchtransitions]; + double val[numberofcontandbatchplaces+2*numberofcontandbatchtransitions]; + + /* + for (int i=1; i<=glp_get_num_rows(lp); i++){ + cout << glp_get_row_name(lp, i) << " : "; + for (int j=1; j<=glp_get_mat_row(lp, i, col, val); j++){ + cout << col[j] << "(" << val[j] << ") - "; + } + cout << glp_get_row_lb(lp, i) << " - " << glp_get_row_ub(lp, i) << endl; + } + */ + glp_delete_prob(lp); + return 0; + +}//======================== + + + +//============================================================================== +//Compute the periodic steady state with assigned transfer speed +//============================================================================== +//1) q_i \le pre(p_i, \cdot) y. +// input and output flow of a place is equal to steady flow. +//To do list +// 2) input and output flow is not equal? what happen + +void BPN::ComputePeriodicSteadyState() +{ + + cout << "\nCompute PeriodicSteadystate\n\n"; + + + double capacity; + double quantity_initial; + double maxflow; + Flow *f; + double z; + + + // contraints a + int beginofcbt = numberofbatchplaces+numberofcontinuousplaces+numberofdiscreteplaces+numberofdiscretetransitions; + int endofcbt = numberofbatchplaces+numberofcontinuousplaces+numberofdiscreteplaces+numberofdiscretetransitions + numberofcontinuoustransitions + numberofbatchtransitions; + int numberofcontandbatchtransitions = numberofcontinuoustransitions + numberofbatchtransitions; + + //constraints b and b' + int beginofbp = numberofdiscreteplaces + numberofcontinuousplaces; + int endofbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; +// int numberofbatchplaces; + + //constraints c + + //constraints d + int beginofcbp = numberofdiscreteplaces; + int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberofcontandbatchplaces = numberofcontinuousplaces + numberofbatchplaces; + + //constraints e + int beginofft = numberofcontandbatchplaces + numberofcontandbatchtransitions; + int endofft = numberofcontandbatchplaces + numberofcontandbatchtransitions + numberofcontandbatchtransitions; + + // set value to all places and transitions + // int numberofcontinuousplaces; + // int numberofcontinuoustransitions; + + // if (numberofcontandbatchtransitions == 0 || numberofcontandbatchplaces ==0) // no need to compute CFF + // return; + + + int nc = 0; // total of contraints + int r = 0; // current contraint + char rname[256]; // row name + + double V[NumberOfTransitions()]; // used to compute the incidence matrix, only continuous and batch positions are used + + + // variables to the linear program + glp_prob *lp; + double SS[numberofcontandbatchplaces+2*numberofcontandbatchtransitions+1]; // to store the result of the linear program + //double *SS; + + nc = numberofcontandbatchtransitions; // contraint a + nc+= numberofbatchplaces; // contraint b + nc+= numberofbatchplaces; // contraint b' + nc+= numberofbatchplaces; // contraint c + nc+= numberofcontandbatchplaces; // contraint d + nc+= numberofcontandbatchplaces; // contraint e + + + // contraints matrix + int ia[nc * (numberofcontandbatchplaces+2*numberofcontandbatchtransitions)]; + int ja[nc * (numberofcontandbatchplaces+2*numberofcontandbatchtransitions)]; + double ar[nc * (numberofcontandbatchplaces+2*numberofcontandbatchtransitions)]; + int arindex; + + // initialising linear program + lp = glp_create_prob(); + glp_set_prob_name(lp, "SS"); + glp_set_obj_dir(lp, GLP_MAX); + glp_add_cols(lp, (numberofcontandbatchplaces+2*numberofcontandbatchtransitions)); + glp_add_rows(lp, nc); + + + // initialising transitions bound + cout << "\nTransitions bound\n\n"; + + //wodes conflict example coefficient. + // glp_set_obj_coef(lp, 3, 1.0); + // glp_set_obj_coef(lp, 6, 10.0); + // glp_set_obj_coef(lp, 8, 20.0); + // glp_set_obj_coef(lp, 9, 1.0); + +//example1 one batch place + glp_set_obj_coef(lp, 1, 1); + glp_set_obj_coef(lp, 2, 1); + + glp_set_obj_coef(lp, 3, 10.0); + glp_set_obj_coef(lp, 4, 10.0); + + // glp_set_obj_coef(lp, 5, 1.0); + // glp_set_obj_coef(lp, 6, 10.0); + + // glp_set_obj_coef(lp, 11, 1.0); + + //example1 two batch place +// glp_set_obj_coef(lp, 1, 1.0); +// glp_set_obj_coef(lp, 3, 10.0); +// glp_set_obj_coef(lp, 2, 1.0); +// glp_set_obj_coef(lp, 4, 10.0); + +// glp_set_obj_coef(lp, 5, 10.0); +// glp_set_obj_coef(lp, 6, 1.0); + + // glp_set_obj_coef(lp, 7, 1.0); + // glp_set_obj_coef(lp, 9, 1.0); +// glp_set_obj_coef(lp, 1, 1.0); +// glp_set_obj_coef(lp, 3, 10.0); +// glp_set_obj_coef(lp, 8, 1.0); +// glp_set_obj_coef(lp, 10, 3.0); + +//wodes+tz1+tz2 +//glp_set_obj_coef(lp, 10, 10.0); +//glp_set_obj_coef(lp, 11, 1.0); +//glp_set_obj_coef(lp, 4, 5.0); + + + + for (int k=beginofcbt; k<endofcbt; k++) { + glp_set_obj_coef(lp, k+1, 1.0); // set (change) objective coefficient or constant term + glp_set_col_name(lp, k+1, transitions[k-numberofcontandbatchplaces]->GetName()); // name of the transition + f = transitions[k-numberofcontandbatchplaces]->GetFlow(); + if (f->GetMaximumFlow() != 0.0) + glp_set_col_bnds(lp, k+1, GLP_DB, 0.0, f->GetMaximumFlow());//set (change) column bounds + else + glp_set_col_bnds(lp, k+1, GLP_FX, 0.0, 0.0); + + cout << transitions[k-numberofcontandbatchplaces]->GetName() << " : 0.0 - " << f->GetMaximumFlow() << endl; + } + + // initialising quantities bound + cout << "\nQuantities bound\n\n"; + for (int k=beginofcbp; k<endofcbp; k++) { + capacity = ((BatchPlace*)places[k])->GetDensity()*((BatchPlace*)places[k])->GetLength(); + // glp_set_obj_coef(lp, k+1, 0.0); // set (change) objective coefficient or constant term + glp_set_col_name(lp, k+1, places[k]->GetName()); // name of the transition + switch (places[k] ->IsA()){ + case Batch_pl: if (capacity != 0.0){ + glp_set_col_bnds(lp, k+1, GLP_DB, 0.0, capacity); + } + else{ + glp_set_col_bnds(lp, k+1, GLP_FX, 0.0, 0.0); + } + cout << places[k]->GetName() << " : 0.0 - " << capacity<<"\n"; + continue; + + break; + + case Continuous_pl: capacity = ((BatchPlace*)places[k+numberofcontinuousplaces])->GetDensity()*((BatchPlace*)places[k+numberofcontinuousplaces])->GetLength(); + glp_set_col_bnds(lp, k+1, GLP_DB, 0.0, capacity); //maybe revised! + cout << places[k]->GetName() << " : 0.0 - "<<capacity<<"\n"; + continue; + break; + } + } + + cout << "\nMinimal firing quantities bound\n\n"; + for (int k=beginofft; k<endofft; k++) { + glp_set_obj_coef(lp, k+1, 1.0e-6); // set (change) objective coefficient or constant term + glp_set_col_name(lp, k+1, transitions[k-numberofcontandbatchplaces-numberofcontandbatchtransitions]->GetName()); // name of the transition + f = transitions[k-numberofcontandbatchplaces-numberofcontandbatchtransitions]->GetFlow(); + if (f->GetMaximumFlow() != 0.0) + glp_set_col_bnds(lp, k+1, GLP_LO, 0.0, 0.0);//set (change) column bounds + else + glp_set_col_bnds(lp, k+1, GLP_FX, 0.0, 0.0); + + cout << transitions[k-numberofcontandbatchplaces-numberofcontandbatchtransitions]->GetName() << " z: >= " << 0.0 << endl; + } + + r = 1; + arindex = 1; + + + cout << "\nStart contraints\n\n"; + // constraint a + cout << "Contraint a\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + sprintf(rname, "a.%d", i); + f = transitions[k-numberofcontandbatchplaces]->GetFlow(); + glp_set_row_name(lp, r, rname); + if (f->GetMaximumFlow() != 0.0) + glp_set_row_bnds(lp, r, GLP_DB, 0.0, f->GetMaximumFlow()); //compare with steadyflow + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = k+1; + ar[arindex] = 1.0; // weigth + arindex++; + r++; + cout << rname << " : " << "0.0 <= y <= " << f->GetMaximumFlow() << endl; + } + + // constraint b +// cout << "Contraint b\n"; +// for (int i=1, k=beginofbp; k<endofbp; k++, i++) { +// sprintf(rname, "b.%d", i); +// capacity= ((BatchPlace*)places[k])->GetDensity() * ((BatchPlace*)places[k])->GetLength(); +// glp_set_row_name(lp, r, rname); +// if (capacity != 0.0 ){ +// glp_set_row_bnds(lp, r, GLP_DB, 0.0, capacity); +// } +// else{ +// glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); +// } +// ia[arindex] = r; +// ja[arindex] = k+1; +// ar[arindex] = 1.0; // weigth +// arindex++; +// r++; +// cout << rname << " : " << " 0.0 <= "<< " q" <<ja[arindex-1] << " <= "<<capacity << endl; +// } + + // constraint b' // q_i + cout << "Contraint b\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + sprintf(rname, "b.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = k+1; + ar[arindex] = 1.0 ; + arindex++; + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfOutputArc(j); + } + } + cout << rname << " : " << "q" <<k+1; + + + for (int j=0, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[j] != 0.0){ + ia[arindex] = r; + ja[arindex] = l+1; + ar[arindex] = -V[j] * ((BatchPlace*)places[k])->GetLength() / ((BatchPlace*)places[k])->GetInstantaneousSpeed() ; + arindex++; + cout << ar[arindex-1]<<"y * " <<j+1; + } + } + cout << "<=0.0" <<endl; + r++; +} + + // Contraint c + cout << "Contraint c\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + maxflow = ((BatchPlace*)places[k])->GetInstantaneousSpeed() * ((BatchPlace*)places[k])->GetDensity(); + + sprintf(rname, "c.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxflow); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfInputArc(j); + } + } + cout << rname << " : "; + for (int j=0, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[j] != 0.0){ + ia[arindex] = r; + ja[arindex] = l+1; + ar[arindex] = V[j]; + arindex++; + cout << "y"<<j+1 << "(" << V[j] << ") + "; + } + } + cout << "<=" << maxflow << endl; + r++; + } + + // constraint d + + cout << "Contraint d\n"; + + for (int i=1, k=beginofcbp; k<endofcbp; k++, i++) { + + sprintf(rname, "d.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); //look after + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + cout << rname<< ":"; + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + // cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + // cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + cout << "y"<<j+1 << "(" << V[j] << ") + "; + } + + for (int j=0, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[j] != 0.0){ + ia[arindex] = r; + ja[arindex] = l+1; + ar[arindex] = V[j]; + arindex++; + + } + } + cout << " = 0.0" << endl; + r++; + } + + + //constraint e + cout << "Contraint e\n"; + for (int i=1, k=beginofcbp; k<endofcbp; k++, i++) { + switch (places[k] ->IsA()){ + case Continuous_pl: quantity_initial =((ContinuousPlace*)places[k])->GetMarks(); + break; + case Batch_pl:quantity_initial= ((BatchPlace*)places[k])->GetInitialQuantity(); + break; + } + sprintf(rname, "e.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, quantity_initial, quantity_initial); + + ia[arindex] = r; + ja[arindex] = k+1; + ar[arindex] = 1.0; // weight + arindex++; + cout << rname<< " : "<<"q"<<k+1; + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + // cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + // cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + cout << "+z"<<j+1 << "(" << V[j] << ") "; + } + + for (int j=0, l=beginofft; l<endofft; j++, l++) { + if (V[j] != 0.0){ + ia[arindex] = r; + ja[arindex] = l+1; + ar[arindex] = -V[j]; + arindex++; + // cout << j << "(" << V[j] << ") - "; + } + } + cout << "=" <<quantity_initial<< endl; + r++; + } + + + glp_term_out(GLP_OFF); + glp_load_matrix(lp, arindex-1, ia, ja, ar); + glp_simplex(lp, NULL); + + cout<<"\nThe steady state is : "<<endl; + z = glp_get_obj_val(lp); + + + + for (int i=1;i<(numberofcontandbatchplaces+2*numberofcontandbatchtransitions+1); i++){ + SS[i]=glp_get_col_prim(lp, i); + //SS = calloc(1+numberofcontandbatchplaces+2*numberofcontandbatchtransitions, sizeof(double)); + } + + for (int i=1;i<(numberofcontandbatchplaces+2*numberofcontandbatchtransitions+1); i++){ + printf("z=%lf,SS[i]=%lf\n",z,i, SS[i]); + // if (i< (numberofcontandbatchplaces+1)){ + +// if (i< (numberofcontandbatchplaces+numberofcontinuoustransitions+1 && i > numberofcontandbatchplaces)){ +// f = ((ContinuousTransition*)transitions[i+numberofcontandbatchplaces-1])->GetFlow(); +// f->SetTheoreticalFlow(SS[i+numberofcontandbatchplaces]); +// f->SetCurrentFlow(SS[i+numberofcontandbatchplaces]); +// } + } + + // f = ((ContinuousTransition*)transitions[k-numberofcontandbatchplaces])->GetFlow(); + // f->SetTheoreticalFlow(SS[k]); + // f->SetCurrentFlow(SS[k]); + + // cout << transitions[k-numberofcontandbatchplaces]->GetName() << " : " << SS[i] << endl; + + int col[numberofcontandbatchplaces+2*numberofcontandbatchtransitions]; + double val[numberofcontandbatchplaces+2*numberofcontandbatchtransitions]; + + /* + for (int i=1; i<=glp_get_num_rows(lp); i++){ + cout << glp_get_row_name(lp, i) << " : "; + for (int j=1; j<=glp_get_mat_row(lp, i, col, val); j++){ + cout << col[j] << "(" << val[j] << ") - "; + } + cout << glp_get_row_lb(lp, i) << " - " << glp_get_row_ub(lp, i) << endl; + } + */ + glp_delete_prob(lp); + return 0; + +}//======================== + + + + + +//==========================Maximal flow based On/OFF control================== +// Compute the controlled firing flow based on maximal flow (MCFF) +//============================================================================== +void BPN::ComputeMCFF() +{ + cout << "\nCompute MCFF\n\n"; + + Flow *u; + double steadyflow; + double maxflow; // maximal outflow of a batch place which depends on the density of output batch and the tranfer speed. + double maxinputflow; //maximal input flow of a batch place which is the product of density and maximal transfer speed. + + + // contraints a + int beginofcbt = numberofdiscretetransitions; + int endofcbt = numberofdiscretetransitions + numberofcontinuoustransitions + numberofbatchtransitions; + int numberofcontandbatchtransitions = numberofcontinuoustransitions + numberofbatchtransitions; + + //constraints b =====>T_z + int numberofcontandbatchtransitionsthatbelongstotz = 0; + for (int i = beginofcbt; i<endofcbt; i++){ + if (transitions[i]->IsFiringQuantityOnState() == 0){ + numberofcontandbatchtransitionsthatbelongstotz++; //T_z + } + } + + //Verifiy if all transitions belong to tz. +// if (numberofcontandbatchtransitionsthatbelongstotz == numberofcontandbatchtransitions ){ +// cout<< "T_z is full\n"; +// } + + if (numberofcontandbatchtransitions == 0) // no need to compute MCFF + return; + + //constraints c ==> constraints c are not enabled transition set and T_ZL. + // int numberofnotenabledcontandbatchtransitions = 0; + int numberofnotenabledorlesssteadyandbelongstofiringquantityofcontandbatchtransitions = 0; + for (int i=beginofcbt; i<endofcbt; i++){ + // if (transitions[i]->GetState() == 0.0 ){ + // numberofnotenabledcontandbatchtransitions++; + // } + if ((transitions[i]->GetState() == 0.0) || ((transitions[i]->IsFiringQuantityOnState() == 0) && (transitions[i]->IsOnState() == 0))){ + numberofnotenabledorlesssteadyandbelongstofiringquantityofcontandbatchtransitions++; //the cardinality of T_ZL + T_N + } + } + + + //constraints d ==> full batch place + int beginofbp = numberofdiscreteplaces + numberofcontinuousplaces; + int endofbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberofcontandbatchplaces = numberofcontinuousplaces + numberofbatchplaces; + int numberoffullbatchplaces = 0; + for (int i=beginofbp; i<endofbp; i++){ + if (((BatchPlace*)places[i])->IsFull() == 1){ + numberoffullbatchplaces++; + } + } + + //constraints e ==> empty continuous places + int beginofcp = numberofdiscreteplaces; + int endofcp = numberofdiscreteplaces + numberofcontinuousplaces; + int numberofemptycontinuousplaces = 0; + for (int i=beginofcp; i<endofcp; i++){ + if (((ContinuousPlace*)places[i])->GetMarks() == 0.0 ){ + numberofemptycontinuousplaces++; + } + } + + + + +//constraints f ==> continuous and batch place whose marking quantity is equal to steady marking quantity (S_E) + // and its input and output transition belongs to T_Z. + +// int beginofcbp = numberofdiscreteplaces; +// int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; +// int numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz = 0; +// +// for (int i=beginofcbp; i<endofcbp; i++){ +// int numberofinputandoutputtransitions = 0; +// int numberofinputandoutputransitionsthatbelongstotz = 0; +// switch (places[i] ->IsA()){ +// case Continuous_pl: +// if (((ContinuousPlace*)places[i])->IsEqualSteadyQuantity() == 1){ +// for (int j=0; j<NumberOfTransitions(); j++) { +// V[j] = 0.0; +// } +// for (int j=0; j<NumberOfTransitions(); j++){ +// if (places[i]->GetWeightOfOutputArc(j) != 0.0 ){ +// V[j] = - places[i]->GetWeightOfOutputArc(j); +// } +// if (places[i]->GetWeightOfInputArc(j) != 0.0 ){ +// V[j] += places[i]->GetWeightOfInputArc(j); +// } +// if (V[j] !=0 ){ +// numberofinputandoutputtransitions++; // no self loop net +// } +// if (V[j] !=0 && transitions[j]->IsFiringQuantityOnState() == 0){ +// numberofinputandoutputransitionsthatbelongstotz++; +// } +// } +// if (numberofinputandoutputtransitions == numberofinputandoutputransitionsthatbelongstotz){ +// numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz++; +// } +// } +// break; +// case Batch_pl: +// if (((BatchPlace*)places[i])->IsEqualSteadyQuantity() == 1){ +// for (int j=0; j<NumberOfTransitions(); j++) { +// V[j] = 0.0; +// } +// for (int j=0; j<NumberOfTransitions(); j++){ +// if (places[i]->GetWeightOfOutputArc(j) != 0.0 ){ +// V[j] = - places[i]->GetWeightOfOutputArc(j); +// } +// if (places[i]->GetWeightOfInputArc(j) != 0.0 ){ +// V[j] += places[i]->GetWeightOfInputArc(j); +// } +// if (V[j] !=0 ){ +// numberofinputandoutputtransitions++; // no self loop net +// } +// if (V[j] !=0 && transitions[j]->IsFiringQuantityOnState() == 0){ +// numberofinputandoutputransitionsthatbelongstotz++; +// } +// } +// if (numberofinputandoutputtransitions == numberofinputandoutputransitionsthatbelongstotz){ +// numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz++; +// } +// } +// break; +// } +// } + + +//constraint f + int beginofcbp = numberofdiscreteplaces; + int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz = 0; + + for (int i=beginofcbp; i<endofcbp; i++){ + switch (places[i] ->IsA()){ + case Continuous_pl: + if (((ContinuousPlace*)places[i])->IsSteadyMarkingReachedandInputOutputTransitionBelongTz() == 1){ + numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz++; + } + break; + case Batch_pl: + if (((BatchPlace*)places[i])->IsSteadyMarkingQuantityReachedandInputOutputTransitionBelongTz() == 1){ + numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz++; + } + break; + } + } + + //constraints g and h. + + + + int nc = 0; // total of contraints + int r = 0; // current contraint + char rname[256]; // row name + + double V[NumberOfTransitions()]; // used to compute the incidence matrix, only continuous and batch positions are used + + + // variables to the linear program + glp_prob *lp; + double MCFF[numberofcontandbatchtransitions]; // to store the result of the linear program + + nc = numberofcontandbatchtransitions; // contraint a + nc+= numberofcontandbatchtransitionsthatbelongstotz; //constraint b + nc+= numberofnotenabledorlesssteadyandbelongstofiringquantityofcontandbatchtransitions; //constraint c + nc+= numberoffullbatchplaces;//constraint d + nc+= numberofemptycontinuousplaces; // constraint e + nc+= numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz; //constaint f + nc+= numberofbatchplaces; //constaint g + nc+= numberofbatchplaces; //constaint h + + + // contraints matrix + int ia[nc * numberofcontandbatchtransitions]; + int ja[nc * numberofcontandbatchtransitions]; + double ar[nc * numberofcontandbatchtransitions]; + int arindex; + + + // initialising linear program + lp = glp_create_prob(); + glp_set_prob_name(lp, "MCFF"); + glp_set_obj_dir(lp, GLP_MAX); + glp_add_cols(lp, numberofcontandbatchtransitions); + glp_add_rows(lp, nc); + + // initialising transitions bound + cout << "\nTransitions bound\n\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + glp_set_obj_coef(lp, i, 1.0); // set (change) objective coefficient or constant term + glp_set_col_name(lp, i, transitions[k]->GetName()); // name of the transition + u = transitions[k]->GetFlow(); + if (u->GetMaximumFlow() != 0.0) + glp_set_col_bnds(lp, i, GLP_DB, 0.0, u->GetMaximumFlow());//set (change) column bounds + else + glp_set_col_bnds(lp, i, GLP_FX, 0.0, 0.0); + + cout << transitions[k]->GetName() << " : 0.0 - " << u->GetMaximumFlow() << endl; + } + + + r = 1; + arindex = 1; + + cout << "\nStart contraints\n\n"; + + // constraint a + cout << "Contraint a\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + sprintf(rname, "a.%d", i); + u = transitions[k]->GetFlow(); + glp_set_row_name(lp, r, rname); + if (u->GetMaximumFlow() != 0.0) + glp_set_row_bnds(lp, r, GLP_DB, 0.0, u->GetMaximumFlow()); //compare with steadyflow + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weight + arindex++; + r++; + cout << rname << " : " << "0.0 <= x <= " << u->GetMaximumFlow() << endl; + } + + + // constraint b T_Z + cout << "Contraint b\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + if (transitions[k]->IsFiringQuantityOnState() == 0){ + sprintf(rname, "b.%d", i); + u = transitions[k]->GetFlow(); + glp_set_row_name(lp, r, rname); + + if (u->GetSteadyFlow() != 0.0) + glp_set_row_bnds(lp, r, GLP_DB, 0.0, u->GetSteadyFlow()); //compare with steadyflow + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weigth + arindex++; + r++; + + cout << rname << " : " << "0.0 <= x <= " << u->GetSteadyFlow() << endl; + } + } + + //constraint c not enabled and T_ZL set into zero. + cout << "Contraint c\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++){ + if (transitions[k]->GetState() == 0.0 || + ((transitions[k]->IsFiringQuantityOnState() == 0 ) && + (transitions[k]->IsOnState() ==0))){ + sprintf(rname, "c.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weight + arindex++; + r++; + cout << rname << " : " << ja[arindex-1] << ": 0.0 = x = 0.0 " << endl; + } + } + + // constraint d Full batch places + cout << "Contraint d\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + if (((BatchPlace*)places[k])->IsFull() == 1){ + sprintf(rname, "d.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, 0.0); //check after + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } + cout << endl; + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << " <= 0.0" << endl; + r++; + } + } + + // constraint e Empty continuous place + cout << "Contraint e\n"; + for (int i=1, k=beginofcp; k<endofcp; k++, i++) { + if (((ContinuousPlace*)places[k])->GetMarks() == 0.0){ + sprintf(rname, "d.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_LO, 0.0, 0.0); //check after + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } + cout << endl; + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << " >= 0.0" << endl; + r++; + } + } + + + //constraint f + cout << "Contraint f\n"; + + for (int i=1, k=beginofcbp; k<endofcbp; k++, i++){ + switch (places[k] ->IsA()){ + case Continuous_pl: + if (((ContinuousPlace*)places[k])->IsSteadyMarkingReachedandInputOutputTransitionBelongTz() == 0) + continue; + break; + case Batch_pl: + if (((BatchPlace*)places[k])->IsSteadyMarkingQuantityReachedandInputOutputTransitionBelongTz() == 0) + continue; + break; + } + +//--------------------------------------------------------------------------- +// for (int i=1, k=beginofcbp; k<endofcbp; k++, i++){ +// int numberofinputandoutputtransitions=0; +// int numberofinputandoutputransitionsthatbelongstotz = 0; +// switch (places[k] ->IsA()){ +// case Continuous_pl: +// if (((ContinuousPlace*)places[k])->IsEqualSteadyQuantity() == 1){ +// for (int j=0; j<NumberOfTransitions(); j++) { +// V[j] = 0.0; +// } +// for (int j=0; j<NumberOfTransitions(); j++){ +// if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ +// V[j] = - places[k]->GetWeightOfOutputArc(j); +// } +// if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ +// V[j] += places[k]->GetWeightOfInputArc(j); +// } +// if (V[j] !=0 ){ +// numberofinputandoutputtransitions++; // no self loop net +// } +// if (V[j] !=0 && transitions[j]->IsFiringQuantityOnState() == 0){ +// numberofinputandoutputransitionsthatbelongstotz++; +// } +// } +// if (numberofinputandoutputtransitions == numberofinputandoutputransitionsthatbelongstotz){ +// continue; +// } +// } +// break; +// +// case Batch_pl: +// if (((BatchPlace*)places[k])->IsEqualSteadyQuantity() == 1){ +// for (int j=0; j<NumberOfTransitions(); j++) { +// V[j] = 0.0; +// } +// for (int j=0; j<NumberOfTransitions(); j++){ +// if (places[i]->GetWeightOfOutputArc(j) != 0.0 ){ +// V[j] = - places[k]->GetWeightOfOutputArc(j); +// } +// if (places[i]->GetWeightOfInputArc(j) != 0.0 ){ +// V[j] += places[k]->GetWeightOfInputArc(j); +// } +// if (V[j] !=0 ){ +// numberofinputandoutputtransitions++; // no self loop net +// } +// if (V[j] !=0 && transitions[j]->IsFiringQuantityOnState() == 0){ +// numberofinputandoutputransitionsthatbelongstotz++; +// } +// } +// if (numberofinputandoutputtransitions == numberofinputandoutputransitionsthatbelongstotz) +// continue; +// } +// break; +// } +//------------------------------------------------------------------------------- + sprintf(rname, "f.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } + cout << endl; + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << " = 0.0" << endl; + r++; + } + + //constraint g + cout << "Contraint g\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++){ + maxinputflow = ((BatchPlace*)places[k])->GetMaxSpeed() * ((BatchPlace*)places[k])->GetDensity(); + sprintf(rname, "g.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxinputflow); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfInputArc(j); + } + } + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << "0.0 <= x <= " << maxinputflow << endl; + r++; + } + + // constraint h + cout << "Contraint h\n"; + + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + maxflow = ((BatchPlace*)places[k])->GetMaxSpeed() * ((BatchPlace*)places[k])->GetDensityOutputBatch(); + sprintf(rname, "h.%d", i); + glp_set_row_name(lp, r, rname); + if (maxflow != 0.0) + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxflow); + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfOutputArc(j); + } + } + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << "0.0 <= x <= " << maxflow << endl; + r++; +} + + glp_term_out(GLP_OFF); + glp_load_matrix(lp, arindex-1, ia, ja, ar); + glp_simplex(lp, NULL); + + for (int i=0, k=beginofcbt; k<endofcbt; k++, i++) { + MCFF[i] = glp_get_col_prim(lp, (i+1)); + u = transitions[k]->GetFlow(); //???continuous transition class? + u->SetTheoreticalFlow(MCFF[i]); + u->SetCurrentFlow(MCFF[i]); + + // cout << transitions[k]->GetName() << " : " << MCFF[i] << endl; + } + + int col[numberofcontandbatchtransitions]; + double val[numberofcontandbatchtransitions]; + +// for (int i=1; i<=glp_get_num_rows(lp); i++){ +// cout << glp_get_row_name(lp, i) << " : "; +// for (int j=1; j<=glp_get_mat_row(lp, i, col, val); j++){ +// cout << col[j] << "(" << val[j] << ") - "; +// } +// cout << glp_get_row_lb(lp, i) << " - " << glp_get_row_ub(lp, i) << endl; +// } + + glp_delete_prob(lp); +////======================================================================= +} + + + +void BPN::ComputeMSCFF() +{ + cout << "\nCompute MCFF\n\n"; + + Flow *u; + double steadyflow; + double maxflow; // maximal outflow of a batch place which depends on the density of output batch and the tranfer speed. + double maxinputflow; //maximal input flow of a batch place which is the product of density and maximal transfer speed. + + + // contraints a + int beginofcbt = numberofdiscretetransitions; + int endofcbt = numberofdiscretetransitions + numberofcontinuoustransitions + numberofbatchtransitions; + int numberofcontandbatchtransitions = numberofcontinuoustransitions + numberofbatchtransitions; + + //constraints b =====>T_z + int numberofcontandbatchtransitionsthatbelongstotz = 0; + for (int i = beginofcbt; i<endofcbt; i++){ + if (transitions[i]->IsFiringQuantityOnState() == 0){ + numberofcontandbatchtransitionsthatbelongstotz++; //T_z + } + } + + if (numberofcontandbatchtransitions == 0) // no need to compute MCFF + return; + + //constraints c ==> constraints c are not enabled transition set and T_ZL. +// int numberofnotenabledcontandbatchtransitions = 0; + int numberofnotenabledorlesssteadyandbelongstofiringquantityofcontandbatchtransitions = 0; + for (int i=beginofcbt; i<endofcbt; i++){ + // if (transitions[i]->GetState() == 0.0 ){ + // numberofnotenabledcontandbatchtransitions++; + // } + if ((transitions[i]->GetState() == 0.0) || ((transitions[i]->IsFiringQuantityOnState() == 0) && (transitions[i]->IsOnState() == 0))){ + numberofnotenabledorlesssteadyandbelongstofiringquantityofcontandbatchtransitions++; //the cardinality of T_ZL + T_N + } + } + + + //constraints d ==> full batch place + int beginofbp = numberofdiscreteplaces + numberofcontinuousplaces; + int endofbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberofcontandbatchplaces = numberofcontinuousplaces + numberofbatchplaces; + int numberoffullbatchplaces = 0; + for (int i=beginofbp; i<endofbp; i++){ + if (((BatchPlace*)places[i])->IsFull() == 1){ + numberoffullbatchplaces++; + } + } + + //constraints e ==> empty continuous places + int beginofcp = numberofdiscreteplaces; + int endofcp = numberofdiscreteplaces + numberofcontinuousplaces; + int numberofemptycontinuousplaces = 0; + for (int i=beginofcp; i<endofcp; i++){ + if (((ContinuousPlace*)places[i])->GetMarks() == 0.0 ){ + numberofemptycontinuousplaces++; + } + } + + + + +//constraints f ==> continuous and batch place whose marking quantity is equal to steady marking quantity (S_E) + // and its input and output transition belongs to T_Z. + + +//constraints f //// 09/04 last version +// int beginofcbp = numberofdiscreteplaces; +// int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; +// int numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz = 0; +// +// for (int i=beginofcbp; i<endofcbp; i++){ +// int numberofinputandoutputtransitions = 0; +// int numberofinputandoutputransitionsthatbelongstotz = 0; +// switch (places[i] ->IsA()){ +// case Continuous_pl: +// if (((ContinuousPlace*)places[i])->IsEqualSteadyQuantity() == 1){ +// for (int j=0; j<NumberOfTransitions(); j++) { +// V[j] = 0.0; +// } +// for (int j=0; j<NumberOfTransitions(); j++){ +// if (places[i]->GetWeightOfOutputArc(j) != 0.0 ){ +// V[j] = - places[i]->GetWeightOfOutputArc(j); +// } +// if (places[i]->GetWeightOfInputArc(j) != 0.0 ){ +// V[j] += places[i]->GetWeightOfInputArc(j); +// } +// if (V[j] !=0 ){ +// numberofinputandoutputtransitions++; // no self loop net +// } +// if (V[j] !=0 && transitions[j]->IsFiringQuantityOnState() == 0){ +// numberofinputandoutputransitionsthatbelongstotz++; +// } +// } +// if (numberofinputandoutputtransitions == numberofinputandoutputransitionsthatbelongstotz){ +// numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz++; +// } +// } +// break; +// case Batch_pl: +// if (((BatchPlace*)places[i])->IsEqualSteadyQuantity() == 1){ +// for (int j=0; j<NumberOfTransitions(); j++) { +// V[j] = 0.0; +// } +// for (int j=0; j<NumberOfTransitions(); j++){ +// if (places[i]->GetWeightOfOutputArc(j) != 0.0 ){ +// V[j] = - places[i]->GetWeightOfOutputArc(j); +// } +// if (places[i]->GetWeightOfInputArc(j) != 0.0 ){ +// V[j] += places[i]->GetWeightOfInputArc(j); +// } +// if (V[j] !=0 ){ +// numberofinputandoutputtransitions++; // no self loop net +// } +// if (V[j] !=0 && transitions[j]->IsFiringQuantityOnState() == 0){ +// numberofinputandoutputransitionsthatbelongstotz++; +// } +// } +// if (numberofinputandoutputtransitions == numberofinputandoutputransitionsthatbelongstotz){ +// numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz++; +// } +// } +// break; +// } +// } + + +//constraint f + int beginofcbp = numberofdiscreteplaces; + int endofcbp = numberofdiscreteplaces + numberofcontinuousplaces + numberofbatchplaces; + int numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz = 0; + + for (int i=beginofcbp; i<endofcbp; i++){ + switch (places[i] ->IsA()){ + case Continuous_pl: + if (((ContinuousPlace*)places[i])->IsSteadyMarkingReachedandInputOutputTransitionBelongTz() == 1){ + numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz++; + } + break; + case Batch_pl: + if (((BatchPlace*)places[i])->IsSteadyMarkingQuantityReachedandInputOutputTransitionBelongTz() == 1){ + numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz++; + } + break; + } + } + + + + + + + + //constraints g and h. + + + + int nc = 0; // total of contraints + int r = 0; // current contraint + char rname[256]; // row name + + double V[NumberOfTransitions()]; // used to compute the incidence matrix, only continuous and batch positions are used + + + // variables to the linear program + glp_prob *lp; + double MSCFF[numberofcontandbatchtransitions]; // to store the result of the linear program + + nc = numberofcontandbatchtransitions; // contraint a + nc+= numberofcontandbatchtransitionsthatbelongstotz; //constraint b + nc+= numberofnotenabledorlesssteadyandbelongstofiringquantityofcontandbatchtransitions; //constraint c + nc+= numberoffullbatchplaces;//constraint d + nc+= numberofemptycontinuousplaces; // constraint e + nc+= numberofequalcontandbatchplacesanditsinputoutputtransitionbelongstotz; //constaint f + nc+= numberofbatchplaces; //constaint g + nc+= numberofbatchplaces; //constaint h + + + // contraints matrix + int ia[nc * numberofcontandbatchtransitions]; + int ja[nc * numberofcontandbatchtransitions]; + double ar[nc * numberofcontandbatchtransitions]; + int arindex; + + + // initialising linear program + lp = glp_create_prob(); + glp_set_prob_name(lp, "MSCFF"); + glp_set_obj_dir(lp, GLP_MAX); + glp_add_cols(lp, numberofcontandbatchtransitions); + glp_add_rows(lp, nc); + + // initialising transitions bound + cout << "\nTransitions bound\n\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + glp_set_obj_coef(lp, i, 1.0); // set (change) objective coefficient or constant term + glp_set_col_name(lp, i, transitions[k]->GetName()); // name of the transition + u = transitions[k]->GetFlow(); + if (u->GetMaximumFlow() != 0.0) + glp_set_col_bnds(lp, i, GLP_DB, 0.0, u->GetMaximumFlow());//set (change) column bounds + else + glp_set_col_bnds(lp, i, GLP_FX, 0.0, 0.0); + + cout << transitions[k]->GetName() << " : 0.0 - " << u->GetMaximumFlow() << endl; + } + + + r = 1; + arindex = 1; + + cout << "\nStart contraints\n\n"; + + // constraint a + cout << "Contraint a\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + sprintf(rname, "a.%d", i); + u = transitions[k]->GetFlow(); + glp_set_row_name(lp, r, rname); + if (u->GetMaximumFlow() != 0.0) + glp_set_row_bnds(lp, r, GLP_DB, 0.0, u->GetMaximumFlow()); //compare with steadyflow + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weight + arindex++; + r++; + cout << rname << " : " << "0.0 <= x <= " << u->GetMaximumFlow() << endl; + } + + + // constraint b T_Z + cout << "Contraint b\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++) { + if (transitions[k]->IsFiringQuantityOnState() == 0){ + sprintf(rname, "b.%d", i); + u = transitions[k]->GetFlow(); + glp_set_row_name(lp, r, rname); + + if (u->GetSteadyFlow() != 0.0) + glp_set_row_bnds(lp, r, GLP_DB, 0.0, u->GetSteadyFlow()); //compare with steadyflow + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weigth + arindex++; + r++; + + cout << rname << " : " << "0.0 <= x <= " << u->GetSteadyFlow() << endl; + } + } + + //constraint c + cout << "Contraint c\n"; + for (int i=1, k=beginofcbt; k<endofcbt; k++, i++){ + if (transitions[k]->GetState() == 0.0 || + ((transitions[k]->IsFiringQuantityOnState() == 0 ) && + (transitions[k]->IsOnState() ==0))){ + sprintf(rname, "c.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + ia[arindex] = r; + ja[arindex] = i; + ar[arindex] = 1.0; // weight + arindex++; + r++; + cout << rname << " : " << ja[arindex-1] << ": 0.0 = x = 0.0 " << endl; + } + } + + // constraint d + cout << "Contraint d\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + if (((BatchPlace*)places[k])->IsFull() == 1){ + sprintf(rname, "d.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, 0.0); //check after + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } + cout << endl; + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << " <= 0.0" << endl; + r++; + } + } + + + + // constraint e + cout << "Contraint e\n"; + for (int i=1, k=beginofcp; k<endofcp; k++, i++) { + if (((ContinuousPlace*)places[k])->GetMarks() == 0.0){ + sprintf(rname, "d.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_LO, 0.0, 0.0); //check after + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } + cout << endl; + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << " >= 0.0" << endl; + r++; + } + } + + + + //constraint f + cout << "Contraint f\n"; + + for (int i=1, k=beginofcbp; k<endofcbp; k++, i++){ + switch (places[k] ->IsA()){ + case Continuous_pl: + if (((ContinuousPlace*)places[k])->IsSteadyMarkingReachedandInputOutputTransitionBelongTz() == 0) + continue; + break; + case Batch_pl: + if (((BatchPlace*)places[k])->IsSteadyMarkingQuantityReachedandInputOutputTransitionBelongTz() == 0) + continue; + break; + } + +//--------------------------------------------------------------------------- +// for (int i=1, k=beginofcbp; k<endofcbp; k++, i++){ +// int numberofinputandoutputtransitions=0; +// int numberofinputandoutputransitionsthatbelongstotz = 0; +// switch (places[k] ->IsA()){ +// case Continuous_pl: +// if (((ContinuousPlace*)places[k])->IsEqualSteadyQuantity() == 1){ +// for (int j=0; j<NumberOfTransitions(); j++) { +// V[j] = 0.0; +// } +// for (int j=0; j<NumberOfTransitions(); j++){ +// if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ +// V[j] = - places[k]->GetWeightOfOutputArc(j); +// } +// if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ +// V[j] += places[k]->GetWeightOfInputArc(j); +// } +// if (V[j] !=0 ){ +// numberofinputandoutputtransitions++; // no self loop net +// } +// if (V[j] !=0 && transitions[j]->IsFiringQuantityOnState() == 0){ +// numberofinputandoutputransitionsthatbelongstotz++; +// } +// } +// if (numberofinputandoutputtransitions == numberofinputandoutputransitionsthatbelongstotz){ +// continue; +// } +// } +// break; +// +// case Batch_pl: +// if (((BatchPlace*)places[k])->IsEqualSteadyQuantity() == 1){ +// for (int j=0; j<NumberOfTransitions(); j++) { +// V[j] = 0.0; +// } +// for (int j=0; j<NumberOfTransitions(); j++){ +// if (places[i]->GetWeightOfOutputArc(j) != 0.0 ){ +// V[j] = - places[k]->GetWeightOfOutputArc(j); +// } +// if (places[i]->GetWeightOfInputArc(j) != 0.0 ){ +// V[j] += places[k]->GetWeightOfInputArc(j); +// } +// if (V[j] !=0 ){ +// numberofinputandoutputtransitions++; // no self loop net +// } +// if (V[j] !=0 && transitions[j]->IsFiringQuantityOnState() == 0){ +// numberofinputandoutputransitionsthatbelongstotz++; +// } +// } +// if (numberofinputandoutputtransitions == numberofinputandoutputransitionsthatbelongstotz) +// continue; +// } +// break; +// } +//------------------------------------------------------------------------------- + sprintf(rname, "f.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = - places[k]->GetWeightOfOutputArc(j); + cout << " - V [" << j << "] " ; + } + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + cout << " + V [" << j << "] " ; + V[j] += places[k]->GetWeightOfInputArc(j); + } + } + cout << endl; + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << " = 0.0" << endl; + r++; + } + + //constraint g + cout << "Contraint g\n"; + for (int i=1, k=beginofbp; k<endofbp; k++, i++){ + maxinputflow = ((BatchPlace*)places[k])->GetMaxSpeed() * ((BatchPlace*)places[k])->GetDensity(); + sprintf(rname, "g.%d", i); + glp_set_row_name(lp, r, rname); + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxinputflow); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfInputArc(j); + } + } + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << "0.0 <= x <= " << maxinputflow << endl; + r++; + } + + + + // constraint h + cout << "Contraint h\n"; + + for (int i=1, k=beginofbp; k<endofbp; k++, i++) { + maxflow = ((BatchPlace*)places[k])->GetMaxSpeed() * ((BatchPlace*)places[k])->GetDensityOutputBatch(); + sprintf(rname, "h.%d", i); + glp_set_row_name(lp, r, rname); + if (maxflow != 0.0) + glp_set_row_bnds(lp, r, GLP_UP, 0.0, maxflow); + else + glp_set_row_bnds(lp, r, GLP_FX, 0.0, 0.0); + + for (int j=0; j<NumberOfTransitions(); j++) { + V[j] = 0.0; + } + for (int j=0; j<NumberOfTransitions(); j++){ + if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ + V[j] = places[k]->GetWeightOfOutputArc(j); + } + } + cout << rname << " : "; + for (int j=1, l=beginofcbt; l<endofcbt; j++, l++) { + if (V[l] != 0.0){ + ia[arindex] = r; + ja[arindex] = j; + ar[arindex] = V[l]; + arindex++; + cout << j << "(" << V[l] << ") - "; + } + } + cout << "0.0 <= x <= " << maxflow << endl; + r++; +} + + glp_term_out(GLP_OFF); + glp_load_matrix(lp, arindex-1, ia, ja, ar); + glp_simplex(lp, NULL); + + for (int i=0, k=beginofcbt; k<endofcbt; k++, i++) { + MSCFF[i] = glp_get_col_prim(lp, (i+1)); + u = transitions[k]->GetFlow(); //???continuous transition class? + u->SetTheoreticalFlow(MSCFF[i]); + u->SetCurrentFlow(MSCFF[i]); + + // cout << transitions[k]->GetName() << " : " << MCFF[i] << endl; + } + + int col[numberofcontandbatchtransitions]; + double val[numberofcontandbatchtransitions]; + +// for (int i=1; i<=glp_get_num_rows(lp); i++){ +// cout << glp_get_row_name(lp, i) << " : "; +// for (int j=1; j<=glp_get_mat_row(lp, i, col, val); j++){ +// cout << col[j] << "(" << val[j] << ") - "; +// } +// cout << glp_get_row_lb(lp, i) << " - " << glp_get_row_ub(lp, i) << endl; +// } + + glp_delete_prob(lp); +////======================================================================= +} diff --git a/src/bpn/bpn.h b/src/bpn/bpn.h new file mode 100644 index 0000000..d51822c --- /dev/null +++ b/src/bpn/bpn.h @@ -0,0 +1,144 @@ +//====================================================================================// +// // +// Batch Petri Nets main class // +// // +//====================================================================================// +// This File: bpn.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 21/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 21/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef BPN_H +#define BPN_H + +class BPN +{ + public: + BPN(); + BPN(const int _numberofplaces, const int _numberoftransitions); + virtual ~BPN(); + + void Copy(const BPN *_bpn); + + + void AllocArcs(); + void AddNodeLinks(); + + //input functions + void PutName(simuleau_name _name); // put a name on the bpn + // place functions + void NumberOfDiscretePlaces(const int n); // set the number of discrete places + void NumberOfContinuousPlaces(const int n); // set the number of continuous places + void NumberOfBatchPlaces(const int n); // set the number of batch places + void NumberOfTriangularBatchPlaces(const int n); // set the number of triangular batch places + int AddPlace(int pos, Place *p); // add a place to the bpn in the position pos + void SetInitialMarking(int pos, int m); // set the initial marking of a discrete place + void SetSteadyMarking(int pos, int m); // set the steady marking of a discrete place + void SetInitialMarking(int pos, double m); // set the initial marking of a conitnuous place + void SetSteadyMarking(int pos, double m); // set the steady marking of a conitnuous place + void AddBatchToInitialMarking(int pos, Batch &b); // set the initial marking of a batch place + void AddBatchToSteadyMarking(int pos, Batch &b); // set the steady marking of a batch place + void AddTriangularToInitialMarking(int pos, ControllableBatch &b); + // set the initial marking of a controllable batch place + void AddTriangularToSteadyMarking(int pos, ControllableBatch &b); + // set the steady marking of a controllable batch place + int AddPlaceOutputArc(int _place, int _transition, double _weight); + // Add an output arc from place to transition + // transition functions + void NumberOfDiscreteTransitions(const int n); // set the number of discrete transitions + void NumberOfContinuousTransitions(const int n); // set the number of continuous transitions + void NumberOfBatchTransitions(const int n); // set the number of batch transitions + int AddTransition(int pos, Transition *t); // add a transition to the bpn in the position pos + int AddTransitionOutputArc(int _transition, int _place, double _weight); + // Add an output arc from transition to place + //output functions + int VerifyName(simuleau_name _name); // verify if _name is already defined in the model + char* GetName(); // get the bpn model name + Node* GetNode(simuleau_name _name); // return the addresse of the node _name; + // place functions + int NumberOfDiscretePlaces(); // return the number of discrete places + int NumberOfContinuousPlaces(); // return the number of continuous places + int NumberOfBatchPlaces(); // return the number of batch places + int NumberOfTriangularBatchPlaces(); // return the number of triangular batch places + int NumberOfPlaces(); // return the number of all places + int GetPlacePosition(simuleau_name _name); // return the position of the place _name + char* GetPlaceName(place_id _place); // return the place name of a place position + Place* GetPlace(place_id _place); // return the place pointer of a place position + place_type GetPlaceType(simuleau_name _name); // return the place type of the place _name + + // transition functions + int NumberOfDiscreteTransitions(); // return the number of discrete transitions + int NumberOfContinuousTransitions(); // return the number of continuous transitions + int NumberOfBatchTransitions(); // return the number of batch transitions + int NumberOfTransitions(); // return the number of all transitions + int GetTransitionPosition(simuleau_name _name); // return the position of the transitions _name + char* GetTransitionName(trans_id _trans); // return the transition name of a transition position + Transition *GetTransition(trans_id _trans); // return the transition pointer of a transition position + trans_type GetTransitionType(simuleau_name _name); // return the transition type of the transition _name + + // print functions + void Print(ostream &fout); + void WritePlaces(ostream &fout); + void WriteFlows(ostream &fout); + + // simulation functions + void ComputeNewMarks(double duration); + void ReserveMarks(); + void CreateBatches(); + void DestructBatches(); + void MergeBatches(); + int ComputeTransitionsStates(); + int StateStability(double *p, double *t); + void ComputeBatchesBehaviours(); + void SetBehaviourFunctions(); + void ComputeIFF(); + void ComputeCFF(); // on/off control method + void ComputeMCFF(); // maximal on/off control method + void ComputeMSCFF(); // near-optimal on/off control method + void ComputeSteadyState(); //Computation of a steady state + void ComputePeriodicSteadyState(); //Computation of a periodic steady state + void ResearchStructuralConflict(); + int VerifyConflict(); + int IsSteadyStateReached(); + void ComputeCurrentFiringQuantity(double steptime); //maximal on/off control method + void ComputeSteadyFiringQuantity(); + + //process event functions + void ComputeNextEventDTF(list<Event> * _dtf); + void ComputeNextEventCPE(list<Event> * _cpe); + void ComputeNextEventDTE(list<Event> * _dte); + void ComputeNextEventBOB(list<Event> * _bob); + void ComputeNextEventDOB(list<Event> * _dob); + void ComputeNextEventBBD(list<Event> * _bbd); + void ComputeNextEventTBM(list<Event> * _tbm); + void ComputeNextEventBMOB(list<Event> * _bmob); + void ComputeNextEventOBD(list<Event> * _obd); + void ComputeNextEventBD(list<Event> * _bd); + void ComputeNextEventBBF(list<Event> * _bbf); + void ComputeNextEventPSQ(list<Event> * _psq); //on off method + void ComputeNextEventRBF(list<Event> * _rbf); //maximal flow based on off method + + + protected: +// int numberofplaces; // number of all places in this model + int numberofdiscreteplaces; // number of discrete places + int numberofcontinuousplaces; // number of continuous places + int numberofbatchplaces; // number of batch places + int numberoftriangularplaces; // number of triangular batch places + +// int numberoftransitions; // number of all transitions in this model + int numberofdiscretetransitions; // number of discrete transitions + int numberofcontinuoustransitions; // number of continuous transitions + int numberofbatchtransitions; // number of batch transitions + + Place **places; // ensemble de places + Transition **transitions; // ensemble de transitions + // double currentfiringquantity; + + private: + simuleau_name bpnname; // BPN model name + +}; + +#endif // BPN_H diff --git a/src/bpn/continuousplace.cpp b/src/bpn/continuousplace.cpp new file mode 100644 index 0000000..61fb12d --- /dev/null +++ b/src/bpn/continuousplace.cpp @@ -0,0 +1,825 @@ +//====================================================================================// +// // +// Continuous place classes inherit of place class // +// // +//====================================================================================// +// This File: continuousplace.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Continuous Place class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +ContinuousPlace::ContinuousPlace() +{ + +} + +//------------------------------------------------------------------------------ +// Named Constructor +//------------------------------------------------------------------------------ +ContinuousPlace::ContinuousPlace(simuleau_name _name):Place(_name) +{ + +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +ContinuousPlace::~ContinuousPlace() +{ + +} + + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void ContinuousPlace::Copy(const ContinuousPlace * _place) +{ + TransferNode(_place); + + marks = _place->marks; + initialmarks = _place->initialmarks; + steadymarks = _place->steadymarks; + reservedmarks = _place->reservedmarks; + nonreservedmarks = _place->nonreservedmarks; + + conflict = _place->conflict; + structuralconflict = _place->structuralconflict; + +} + +//------------------------------------------------------------------------------ +// It set the initial marking of the place +//------------------------------------------------------------------------------ +void ContinuousPlace::SetInitialMarking(double m) +{ + marks = initialmarks = nonreservedmarks = m; + reservedmarks = 0; +} + + +//----------------------------------------------------------------------------- +//It returns the initial marking of a place +//---------------------------------------------------------------------------- +double ContinuousPlace::GetInitialMarks() +{ + return(initialmarks); +} + + +//------------------------------------------------------------------------------ +// It set the steady marking of the place +//------------------------------------------------------------------------------ +void ContinuousPlace::SetSteadyMarking(double m) +{ + steadymarks = m; +} + +//------------------------------------------------------------------------------ + +// It returns the steady marking of the place +//---------------------------------------------------------------------- +double ContinuousPlace::GetSteadyMarks() +{ + return (steadymarks); +} + +//------------------------------------------------------------------------------ +// It returns the place marks +//------------------------------------------------------------------------------ +double ContinuousPlace::GetMarks() +{ + return (marks); +} + +//------------------------------------------------------------------------------ +// It changes the place marks +//------------------------------------------------------------------------------ +void ContinuousPlace::ChangeMarks(double m) +{ + marks = nonreservedmarks = m; + if (abs(m) < PRF::prf.Min_Err()){ + marks = nonreservedmarks = 0.0; + } +} + + +//------------------------------------------------------------------------------ +// It reduces the place marks +//------------------------------------------------------------------------------ +void ContinuousPlace::ReduceMarks(double m) +{ + nonreservedmarks -= m; + marks = nonreservedmarks + reservedmarks; + if (abs(marks) < PRF::prf.Min_Err()){ + marks = nonreservedmarks = reservedmarks = 0.0; + } +} + +//------------------------------------------------------------------------------ +// It reserve the place marks +//------------------------------------------------------------------------------ +void ContinuousPlace::ReserveMarks(double m) +{ + reservedmarks += m; + nonreservedmarks = marks - reservedmarks; +} + +//------------------------------------------------------------------------------ +// It remove the reserved marks in the place +//------------------------------------------------------------------------------ +void ContinuousPlace::RemoveReservedMarks(double m) +{ + reservedmarks -= m; + marks = nonreservedmarks + reservedmarks; + if (abs(marks) < PRF::prf.Min_Err()){ + marks = nonreservedmarks = reservedmarks = 0.0; + } +} + +//------------------------------------------------------------------------------ +// It adds the marks to the place +//------------------------------------------------------------------------------ +void ContinuousPlace::AddMarks(double m) +{ + marks += m; + nonreservedmarks = marks -reservedmarks; + + /*if (nonreservedmarks < 0.0){ + nonreservedmarks = 0.0; + marks = nonreservedmarks + reservedmarks; + } + if (marks < 0.0){ + marks = 0.0; + nonreservedmarks = 0.0; + reservedmarks = 0.0; + }*/ +} + +//------------------------------------------------------------------------------ +// It compute the continuous place state +// TODO verfiy method and definition 9 in Demongodin thesis +//------------------------------------------------------------------------------ +void ContinuousPlace::ComputeState() +{ + int counter = 0; + Transition *t; + + if (GetNumberOfOutputArcs() == 0){ + state = 0.0; + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t = outputnodes[i]; + } + } + + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: if (nonreservedmarks > 0.0){ + state = 1.0; // continuous place not empty + } + else{ + state = PlaceIsFed(); // in case of an empty place + } + break; + case Discrete_tr: if (reservedmarks != 0.0){ + state = 0.5; + } + else{ // there is no reserved marks + for (int i=0; i<numberofarcs; i++){ + if ((outputarcs[i] != 0.0 ) && (nonreservedmarks < (outputarcs[i] - PRF::prf.Min_Err()))){ + counter++; + } + } + if (counter == 0){ + state = 1.0; + } + else{ + state = 0.0; + } + } + break; + } + } + + //cout << "\nstate of a continuous place : " << state << endl; +} + + +//------------------------------------------------------------------------------ +// It evolves the marks in the place +//------------------------------------------------------------------------------ +void ContinuousPlace::EvolveMarks(double _date) +{ + VerifyMarks(); +} + +//------------------------------------------------------------------------------ +// It evolves the marks in the place +//------------------------------------------------------------------------------ +void ContinuousPlace::VerifyMarks() +{ + if ((nonreservedmarks < 0.0) || ((nonreservedmarks < PRF::prf.Min_Err()) && (nonreservedmarks > - PRF::prf.Min_Err()))){ + nonreservedmarks = 0.0; + marks = nonreservedmarks + reservedmarks; + } + if (((marks < PRF::prf.Min_Err()) && (marks > - PRF::prf.Min_Err())) || (marks < 0.0)){ + marks = 0.0; + nonreservedmarks = 0.0; + reservedmarks = 0.0; + } +} + + + + +//------------------------------------------------------------------------------ +// It verifies effectif conflits +//------------------------------------------------------------------------------ +int ContinuousPlace::VerifyConflict() +{ + int necessarymarks = 0; + int numberoftransitionsinconflict = 0; + double currentflow = 0.0; + + Transition *t; + Flow *f; + + conflict = 0; + + if (structuralconflict){ + if (GetNumberOfOutputArcs() == 0){ //why the output arcs are zero when it has a strucral conflict ----29/01/2020 + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ +// t = simulation->sbpn->GetTransition(i); + t = outputnodes[i]; + if ((t->GetState()!=1)) { + f = t->GetFlow(); + if (f->GetCurrentFlow()){ + numberoftransitionsinconflict++; + } + } + } + } + + if (numberoftransitionsinconflict > 1){ + conflict = 2; + return (2); + } + } + } + return (0); +} + + +//------------------------------------------------------------------------------ +// It computes if the place is fed (has an input flow) +//------------------------------------------------------------------------------ +double ContinuousPlace::PlaceIsFed() +{ + double pre = 0.0; + double transitionstate; + + Transition *t; + + if (GetNumberOfInputArcs() == 0){ + return (Not_fed); + } + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t = inputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: transitionstate = t->GetState(); + pre = max(pre, transitionstate); + break; + } + } + } + if (pre == 0.0){ + return (Not_fed); + } + else{ + return (Fed); + } +} + +//==========================WOdes================================================ +//------------------------------------------------------------------------------ +// It returns true if the continuous place reaches steady marking quantity +//------------------------------------------------------------------------------ +int ContinuousPlace::IsEqualSteadyQuantity() +{ + if (abs(steadymarks - marks) < PRF::prf.Min_Err()) + return 1; + return 0; + } + +//------------------------------------------------------------------------------ +// It returns true if the marking quantity of continuous place is greater than steady marking quantity +//------------------------------------------------------------------------------ +int ContinuousPlace::IsGreaterThanSteadyQuantity() +{ + if ((marks - steadymarks) > PRF::prf.Min_Err()) + return 1; + return 0; +} + +//------------------------------------------------------------------------------ +// It returns true if the marking quantity of continuous place is less than steady marking quantity +//------------------------------------------------------------------------------ +int ContinuousPlace::IsLessThanSteadyQuantity() +{ + if ((abs(marks - steadymarks) > PRF::prf.Min_Err()) && ((marks - steadymarks) < 0.0)) + return 1; + return 0; + +} + +//------------------------------------------------------------------------------ +// It returns true if the marking of continuous place is equal than steady marking +//------------------------------------------------------------------------------ +int ContinuousPlace::IsSteadyMarkingReached() +{ + if (abs(steadymarks - marks) < PRF::prf.Min_Err()) + return 1; + return 0; + +} +//============================================================================= + +//===================Vecos================================================== +// It returns ture if the marking of continuous place is equal to steady marking +// and all of its input and output transition belongs to T_Z. +//========================================================================== +int ContinuousPlace::IsSteadyMarkingReachedandInputOutputTransitionBelongTz() +{ + Transition *t; + double weight; + int placestate =0; + int counter = 0; + int countertz=0; + + + if (abs(steadymarks - marks) < PRF::prf.Min_Err()){ + if (GetNumberOfOutputArcs() == 0){ + return 1; // the conservative net and consistent net + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t=outputnodes[i]; + counter++; + } + if (outputarcs[i] != 0.0 && t->IsFiringQuantityOnState()==0) + countertz++; + + } + } + + if (GetNumberOfInputArcs() == 0){ + return 1; // the conservative net and consistent net + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t=inputnodes[i]; + counter++; + } + if (inputarcs[i] != 0.0 && t->IsFiringQuantityOnState()==0) + countertz++; + + } + } + if (counter == countertz) + return 1; + return placestate; + } + return placestate; +} + +//------------------------------------------------------------------------------ +// It computes the input flow of a fed place +//------------------------------------------------------------------------------ +double ContinuousPlace::ComputeFlowFedPlace(ContinuousTransition *ct) +{ + Transition *t; + Flow *f = ct->GetFlow(); + double fedplaceflow = f->GetTheoreticalFlow(); + double transitionflow; + double preflow = 0.0; + double postflow = 0.0; + + + if (fedplaceflow < 0.0){ // infinite flow + return (fedplaceflow); + } + + if (GetNumberOfInputArcs() == 0){ + preflow = 0.0 ; + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t = inputnodes[i]; + switch(t->IsA()){ + case Continuous_tr: + case Batch_tr: f = t->GetFlow(); + transitionflow = f->GetTheoreticalFlow(); + if (transitionflow < 0.0){ // infinite flow + postflow = -1.0; + i = numberofarcs; + } + else{ + postflow += (inputarcs[i] * transitionflow); + } + break; + } + } + } + } + + // if the input flow isn't infinite, compute the output flow + if (postflow < 0.0){ + return (postflow); + } + else{ + if (GetNumberOfOutputArcs() != 0){ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t = outputnodes[i]; + switch(t->IsA()){ + case Continuous_tr: + case Batch_tr: f = t->GetFlow(); + transitionflow = f->GetTheoreticalFlow(); + if (transitionflow < 0.0){ // infinite flow + preflow = -1.0; + i = numberofarcs; + } + else{ + preflow += (outputarcs[i] * transitionflow); + } + break; + } + } + } + } + } + + if (preflow < 0.0){ // infinite flow + return (-1.0); + } + else{ + fedplaceflow = fedplaceflow - preflow + postflow; + return (fedplaceflow); + } +} + + + +//------------------------------------------------------------------------------ +// It computes the date of the next event to Continuous Place becomes Enabled type +// return -1 for no event and event date otherwise +//------------------------------------------------------------------------------ +double ContinuousPlace::GetCPEEvent() +{ + Transition *t; + Flow *f; + double transitionflow = 0.0; + double weightflow = 0.0; + double eventdate = -2.0; + + if (GetNumberOfOutputArcs()){ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t = outputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: f = t->GetFlow(); + transitionflow = f->GetCurrentFlow(); + if (transitionflow <= 0.0) { // infinit flow + eventdate = -1.0; + i = numberofarcs; // stop loop for + } + else{ + weightflow -= (outputarcs[i] * transitionflow); + } + break; + } + } + } + } + + if (eventdate == -1.0){ + return (eventdate); + } + else{ + if (GetNumberOfInputArcs()){ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ +// t = simulation->sbpn->GetTransition(i); + t = inputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: f = t->GetFlow(); + transitionflow = f->GetCurrentFlow(); + if (transitionflow > 0.0) { // non infinit flow + weightflow += (inputarcs[i] * transitionflow); + } + break; + } + } + } + } + } + if ((weightflow != 0.0)){ + eventdate = simulation->stime->GetCurrentDate() - (nonreservedmarks/weightflow); + } + return (eventdate); +} + + +//------------------------------------------------------------------------------ +// It computes the date of the next event to Discrete Transistion becomes Enabled type +//------------------------------------------------------------------------------ +double ContinuousPlace::GetDTEEvent() +{ + Transition *t; + double eventdate = -1.0; + double result; + + if (GetNumberOfOutputArcs()){ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ +// t = simulation->sbpn->GetTransition(i); + t = outputnodes[i]; + switch (t->IsA()){ + // cas où la transition aval est une transition discrete ----- + // ATTENTION !!!!!! + // SUPPOSE QUE TOUTE PLACE CONTINUE A + // UNE ET UNE SEULE TRANISTION DISCRETE AVAL + case Discrete_tr: result = ComputeDateDTEEvent(t, outputarcs[i]); + if ((result <= 0.0) && (result != simulation->stime->GetCurrentDate())){ // infinit flow + eventdate = -1.0; + i = numberofarcs; + } + else{ + eventdate = result; + } + break; + } + } + } + } + return (eventdate); +} + + +//-----------------On off Code------------------------------------------------- +// It computes the date of the next event to marking quantity of a batch place +// reaches its steady marking quantity (Place reaches Steady marking Quantity). +//------------------------------------------------------------------------------ +/*double ContinuousPlace::GetPSQEvent() +{ + double steadymarks; // we need input this value before the simulation. !!! + double marks; + double date; + double outputtransitionflow = 0; + Transition *t; + Flow *u; + InFlow *I; + + if (abs(marks - steadymarks) < PRF::prf.Min_Err()){ + return (date); + } + else{ + for (int i=0; i<numberofarcs; int j=0; j<numberofarcs; i++,j++){ + if (outputarcs[i] != 0.0 || inputarcs[j] != 0.0){ + t = outputnodes[i]; + m = inputnodes[j]; + switch (t->IsA()){ + case Batch_tr: u = t->GetFlow(); + I = m->GetFlow(); + inputtransitionflow = m->GetFlow(); + outputtransitionflow = u->GetCurrentFlow(); + date = (ContinuousPlace::GetMarks()-steadymarks) / (ContinuousPlace::GetOutflow - inputtransitionflow); + date += simulation->stime->GetCurrentDate(); + break; + case Continuous_tr: u = t->GetFlow(); + I = m->GetFlow(); + inputtransitionflow = m->GetCurrentFlow(); + outputtransitionflow = u->GetCurrentFlow(); + date = (ContinuousPlace::GetMarks()-steadymarks) / (outputtransitionflow - inputtransitionflow); + date += simulation->stime->GetCurrentDate(); + break; + } +} + return (date); +} +} +}*/ + +//============================PSQ event===================== +// +//=========================================================== + +double ContinuousPlace::GetPSQEvent() +{ + double steadymarks=0.0; + double marks=0.0; + double transitionflow = 0.0; + double weightflow = 0.0; + double eventdate = -2.0; + Transition *t; + Flow *f; + + if (abs(GetMarks() - GetSteadyMarks()) < PRF::prf.Min_Err()){ + eventdate= simulation->stime->GetCurrentDate(); + } + else{ + if (GetNumberOfOutputArcs()){ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ +// t = simulation->sbpn->GetTransition(i); + t = outputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: f = t->GetFlow(); + transitionflow = f->GetCurrentFlow(); + weightflow -= (outputarcs[i] * transitionflow); + break; + } + } + } + } + + if (GetNumberOfInputArcs()){ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ +// t = simulation->sbpn->GetTransition(i); + t = inputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: f = t->GetFlow(); + transitionflow = f->GetCurrentFlow(); + + weightflow += (inputarcs[i] * transitionflow); + + break; + } + } + } + } + if ((weightflow != 0.0)){ + eventdate = simulation->stime->GetCurrentDate() - ((GetMarks()-GetSteadyMarks())/weightflow); + } + return (eventdate); +} +} + + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void ContinuousPlace::Print(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Continuous" << endl; + fout << " Marks: " << marks << endl; + fout << " Initial Marks: " << initialmarks << endl; + if (steadymarks!=-1.0) + fout << " Steady Marks: " << steadymarks << endl; + fout << " Reserved Marks: " << reservedmarks << endl; + fout << " Non Reserved Marks: " << nonreservedmarks << endl; + fout << " Arcs: " << endl; + PrintArcs(fout); +} + +//------------------------------------------------------------------------------ +// Write +//------------------------------------------------------------------------------ +void ContinuousPlace::Write(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Continuous" << endl; + fout << " Marks: " << marks << endl; + if (steadymarks!=-1.0){ + fout << " Steady Marks: " << steadymarks; + if (IsSteadyMarkingReached()) + fout << " (steady marking reached)"; + fout << endl; + } + fout << " Reserved Marks: " << reservedmarks << endl; +} + + +//------------------------------------------------------------------------------ +// It computes the date of the next event DTE for a specific transition +// It return -1.0 if transtion if already enabled and eventdate otherwise +//------------------------------------------------------------------------------ +double ContinuousPlace::ComputeDateDTEEvent(DiscreteTransition *t, double weight) +{ + double inputflow; + double m; + double eventdate; + + if (t->GetState() != 0.0){ // transition is already enabled + return (-1.0); + } + else{ // compute the next validation + inputflow = ComputeInputFlow(); + if (inputflow != 0.0){ + m = weight - nonreservedmarks; + eventdate = m / inputflow; + eventdate += simulation->stime->GetCurrentDate(); + return (eventdate); + } + else{ + return (-1.0); + } + } +} + +//------------------------------------------------------------------------------ +// It computes the input flow for the continuous place +//------------------------------------------------------------------------------ +double ContinuousPlace::ComputeInputFlow() +{ + double inputflow = 0.0; + double transitionflow; + Flow *f; + Transition *t; + + if (GetNumberOfInputArcs()){ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ +// t = simulation->sbpn->GetTransition(i); + t = inputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: if (t->GetState() != 0.0){ // test if the transition (continuous or batch) was validated + f = t->GetFlow(); + transitionflow = f->GetCurrentFlow(); + inputflow += (inputarcs[i] * transitionflow); + } + break; + } + } + } + } + return (inputflow); +} + +//=============================Outputflowof continuous place======= +// +//================================================================= + +/*double ContinuousPlace::ComputeOutputFlow() +{ + double outputflow = 0.0; + double transitionflow; + Flow *f; + Transition *t; + + if (GetNumberOfOutputArcs()){ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ +// t = simulation->sbpn->GetTransition(i); + t = outputnodes[i]; + switch (t->IsA()){ + case Continuous_tr: + case Batch_tr: if (t->GetState() != 0.0){ // test if the transition (continuous or batch) was validated + f = t->GetFlow(); + transitionflow = f->GetCurrentFlow(); + outputflow += (outputarcs[i] * transitionflow); + } + break; + } + } + } + } + return (outputflow); +} + +*/ diff --git a/src/bpn/continuoustransition.cpp b/src/bpn/continuoustransition.cpp new file mode 100644 index 0000000..d0d9772 --- /dev/null +++ b/src/bpn/continuoustransition.cpp @@ -0,0 +1,315 @@ +//====================================================================================// +// // +// Continuous transition classes inherit of transition class // +// // +//====================================================================================// +// This File: continuoustransition.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + + + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Continuous Transition class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +ContinuousTransition::ContinuousTransition() +{ + +} + +//------------------------------------------------------------------------------ +// Named Constructor +//------------------------------------------------------------------------------ +ContinuousTransition::ContinuousTransition(simuleau_name _name, double _flow, double _steadyflow):Transition(_name) +{ + flow = new Flow; + flow->SetAllFlows(_flow); + flow->SetSteadyFlow(_steadyflow); + +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +ContinuousTransition::~ContinuousTransition() +{ + if (flow) + delete flow; +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void ContinuousTransition::Copy(const ContinuousTransition *_transition) +{ + TransferNode(_transition); + flow = new Flow; + flow->Copy(_transition->flow); // transition flows + firingquantity = new FiringQuantity; + firingquantity->Copy(_transition->firingquantity); +} + + +//------------------------------------------------------------------------------ +// Returns flows +//------------------------------------------------------------------------------ +Flow* ContinuousTransition::GetFlow() +{ + return (flow); +} + +//------------------------------------------------------------------------------ +// set the initial flow +//------------------------------------------------------------------------------ +void ContinuousTransition::SetInitialFlow(double _flow) +{ + flow->SetInitialFlow(_flow); +} + +//------------------------------------------------------------------------------ +// set the initial flow +//------------------------------------------------------------------------------ +void ContinuousTransition::SetTheoreticalFlow(double _flow) +{ + flow->SetTheoreticalFlow(_flow); +} + +//------------------------------------------------------------------------------ +// It returns true if the current flow is equal to the steady flow +//------------------------------------------------------------------------------ +int ContinuousTransition::IsSteadyFlowReached() +{ + if (abs(flow->GetCurrentFlow() - flow->GetSteadyFlow()) < PRF::prf.Min_Err()) + return 1; + return 0; +} + +//------------------------------------------------------------------------------ +// Compute minimum positive flow +//------------------------------------------------------------------------------ +double ContinuousTransition::ComputeMinimumFlow(double f1, double f2) +{ + double minimum; + + if ((f1 >= 0.0) && (f2 >= 0.0)){ + minimum = min(f1,f2); + } + else { + if ((f1 < 0.0) && (f2 < 0.0)){ + minimum = f2; + } + if (f1 < 0.0){ + minimum = f2; + } + if (f2 < 0.0) { + minimum = f1; + } + } + return (minimum); +} + +//------------------------------------------------------------------------------ +// It computes the theoretical flow +//------------------------------------------------------------------------------ +void ContinuousTransition::ComputeTheoreticalFlow() +{ + double flowvalue; + + + if (state == 0.0){ // not enable transition + flowvalue = 0.0; // null flow + } + else{ + if (state == 1.0){ // transition is strongly validated + flowvalue = flow->GetMaximumFlow(); + } + else{ + flowvalue = ComputeMinimumFlow(flow->GetMaximumFlow(), ComputeTheoreticalFlowOfPlace()); + } + flow->SetTheoreticalFlow(flowvalue); + } +} + +//------------------------------------------------------------------------------ +// Fire transition +//------------------------------------------------------------------------------ +void ContinuousTransition::WalkThrough(double duration) +{ + if (duration > 0.0) + FireContinuousTransition(duration); +} + +//------------------------------------------------------------------------------ +// Fire continuous transition +//------------------------------------------------------------------------------ +void ContinuousTransition::FireContinuousTransition(double duration) +{ + double quantity; + double curflow; + double weight; + Place *p; + + curflow = flow->GetCurrentFlow(); + + // not fireable transition + if ((curflow == 0.0) || (duration == 0.0)) + return; + + quantity = curflow * duration; + + // remove marks of the input places + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ + weight = inputarcs[i]; +// p = simulation->sbpn->GetPlace(i); + p = inputnodes[i]; + + switch (p->IsA()){ + case Continuous_pl : ((ContinuousPlace*)p)->ReduceMarks(weight * quantity); +// cout << "reducing from :" << i << " val: " << weight * quantity << endl; + break; + } + } + } + + // add marks of the output places + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ + weight = outputarcs[i]; +// p = simulation->sbpn->GetPlace(i); + p = outputnodes[i]; + + switch (p->IsA()){ + case Continuous_pl : ((ContinuousPlace*)p)->AddMarks(weight * quantity); +// cout << "adding to :" << i << " val: " << weight * quantity << endl; + break; + } + } + } +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void ContinuousTransition::Print(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Continuous" << endl; + fout << " Flow: " << endl; + flow->Print(fout); + fout << " Arcs: " << endl; + PrintArcs(fout); +} + +//------------------------------------------------------------------------------ +// It writes the transition flows +//------------------------------------------------------------------------------ +void ContinuousTransition::Write(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Continuous" << endl; + fout << " State: " << state << endl; + fout << " Current Flow: " << flow->GetCurrentFlow() << endl; + if (flow->GetSteadyFlow() != -1.0) + fout << " Steady Flow: " << flow->GetSteadyFlow() << endl; + +} + + +//------------------------------------------------------------------------------ +// It computes the theoretical flow taking into account the input places +// TODO verify flow when non place is fed +//------------------------------------------------------------------------------ +double ContinuousTransition::ComputeTheoreticalFlowOfPlace() +{ + double placeflow, f; + double placestate; + + Place *p; + + if (GetNumberOfInputArcs() == 0){ + return (flow->GetMaximumFlow()); + } + + placeflow = flow->GetMaximumFlow(); + + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ +// p = simulation->sbpn->GetPlace(i); + p = inputnodes[i]; + + switch (p->IsA()){ + case Continuous_pl : placestate = p->GetState(); + if (placestate == 0.5){ // place is fed + f = ((ContinuousPlace*)p)->ComputeFlowFedPlace(this); + placeflow = ComputeMinimumFlow(placeflow, f); + } + break; + } + } + } + return (placeflow); +} + +//========================RBF========Event================================= +// It returns the rbf event for each continuous transition: +//=========================================================================== +double ContinuousTransition::GetRBFEvent() +{ + double date; + double min_date = -1.0; + double weight; + double transitionflow; + Place *p; +// Transition *t; +// FiringQuantity *q; + double Zs; + double z; + + // q=t->GetFiringQuantity(); + Zs=firingquantity->GetSteadyFiringQuantity(); + z =firingquantity->GetCurrentFiringQuantity(); + + if (GetNumberOfOutputArcs() == 0){ + return (-1.0); + } + else if(z >= Zs){ + return (-1.0); + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ +// p = simulation->sbpn->GetPlace(i); + p = (Place*)outputnodes[i]; + + weight = outputarcs[i]; + // f=t->GetFlow(); + transitionflow=flow->GetCurrentFlow(); + switch (p->IsA()){ + case Continuous_pl : + date = (Zs-z) / transitionflow; // FreeSteadyMarkingQuantity= 0 in P^C + date += simulation->stime->GetCurrentDate(); + break; + case Batch_pl : + break; + } + } + if (date < min_date || min_date==-1.0){ + min_date= date; + } + } + return (min_date); + } + return (-1.0); +} +//----------------------------------------------------------------------------------- diff --git a/src/bpn/controllablebatch.cpp b/src/bpn/controllablebatch.cpp new file mode 100644 index 0000000..470b17d --- /dev/null +++ b/src/bpn/controllablebatch.cpp @@ -0,0 +1,404 @@ +//====================================================================================// +// // +// Controllable Batch class // +// // +//====================================================================================// +// This File: controllablebatch.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 28/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 28/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Triangular Batch class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +ControllableBatch::ControllableBatch():Batch() +{ + speed = 0.0; + state = Free_st; + behaviour = Free_behaviour; + evolvefunction = NULL; +} + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +ControllableBatch::ControllableBatch(char *_name):Batch(_name) +{ + speed = 0.0; + state = Free_st; + behaviour = Free_behaviour; + evolvefunction = NULL; +} + +//------------------------------------------------------------------------------ +// Initialized constructor +//------------------------------------------------------------------------------ +ControllableBatch::ControllableBatch(double _length, double _density, double _position, double _speed):Batch(_length, _density, _position) +{ + speed = _speed; + state = Free_st; + behaviour = Free_behaviour; + evolvefunction = NULL; +} + +//------------------------------------------------------------------------------ +// Initialized constructor +//------------------------------------------------------------------------------ +ControllableBatch::ControllableBatch(double _inputflow, double _speed):Batch(_inputflow, _speed) +{ + speed = _speed; + state = Free_st; + behaviour = Free_behaviour; + evolvefunction = NULL; +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +ControllableBatch::~ControllableBatch() +{ + +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void ControllableBatch::Copy(const ControllableBatch &_controllablebatch) +{ + strcpy(name, _controllablebatch.name); + length = _controllablebatch.length; + density = _controllablebatch.density; + position = _controllablebatch.position; + outputflow = _controllablebatch.outputflow; + + speed = _controllablebatch.speed; + state = _controllablebatch.state; + behaviour = _controllablebatch.behaviour; + evolvefunction = _controllablebatch.evolvefunction; +} + +//------------------------------------------------------------------------------ +// IsEqual +//------------------------------------------------------------------------------ +int ControllableBatch::IsEqual(const ControllableBatch &_controllablebatch) +{ + if (length != _controllablebatch.length) + return 0; + if (density != _controllablebatch.density) + return 0; + if (position != _controllablebatch.position) + return 0; + if (speed != _controllablebatch.speed) + return 0; + return 1; +} + +//------------------------------------------------------------------------------ +// It sets a new speed +//------------------------------------------------------------------------------ +void ControllableBatch::SetSpeed(double _speed) +{ + speed = _speed; +} + +//------------------------------------------------------------------------------ +// It sets a new state +//------------------------------------------------------------------------------ +void ControllableBatch::SetState(ctrl_batch_state _state) +{ + state = _state; +} + +//------------------------------------------------------------------------------ +// It sets a new behaviour +//------------------------------------------------------------------------------ +void ControllableBatch::SetBehaviour(ctrl_batch_behaviour _behaviour) +{ + behaviour = _behaviour; +} + +//------------------------------------------------------------------------------ +// It returns the speed +//------------------------------------------------------------------------------ +double ControllableBatch::GetSpeed() +{ + return (speed); +} + +//------------------------------------------------------------------------------ +// It returns the batch flow +//------------------------------------------------------------------------------ +double ControllableBatch::GetFlow() +{ + return (speed * density); +} + +//------------------------------------------------------------------------------ +// It returns the state +//------------------------------------------------------------------------------ +ctrl_batch_state ControllableBatch::GetState() +{ + return (state); +} + +//------------------------------------------------------------------------------ +// It returns the state +//------------------------------------------------------------------------------ +ctrl_batch_state ControllableBatch::GetState(TriangularBatchPlace *tbp) +{ + double ratio = tbp->GetMaxFlow() / tbp->GetInstantaneousSpeed(); + + if ((density - ratio) < PRF::prf.Min_Err()) + state = Free_st; + else + state = Congested_st; + + return (state); +} + +//------------------------------------------------------------------------------ +// It returns the state name +//------------------------------------------------------------------------------ +char* ControllableBatch::GetStateName() +{ + switch (state) { + case No_st : return ("None"); + case Free_st : return ("Free"); + case Congested_st : return ("Congested"); + default : return ("None"); + } + +} + +//------------------------------------------------------------------------------ +// It returns the behaviour +//------------------------------------------------------------------------------ +ctrl_batch_behaviour ControllableBatch::GetBehaviour() +{ + return (behaviour); +} + +//------------------------------------------------------------------------------ +// It returns the behaviour name +//------------------------------------------------------------------------------ +char* ControllableBatch::GetBehaviourName() +{ + switch (behaviour) { + case No_behaviour : return ("None"); + case Free_behaviour : return ("Free"); + case Congesting_behaviour : return ("Congesting"); + case Uncongesting_behaviour : return ("Uncongesting"); + default : return ("None"); + } +} + +//------------------------------------------------------------------------------ +// It returns the behaviour +//------------------------------------------------------------------------------ +int ControllableBatch::IsOutputControllableBatch(BatchPlace *bp) +{ + if ((bp->GetLength() - position) < PRF::prf.Min_Err()) + return (1); + else + return (0); +} + +//------------------------------------------------------------------------------ +// It returns true if this batch is in contact with another batch by the front +//------------------------------------------------------------------------------ +int ControllableBatch::IsInContactWithByFront(ControllableBatch &cb) +{ + if (((cb.GetPosition() - cb.GetLength()) - GetPosition()) < PRF::prf.Min_Err()) + return (1); + else + return (0); +} + +//------------------------------------------------------------------------------ +// It returns true if this batch is in contact with another batch by the rear +//------------------------------------------------------------------------------ +int ControllableBatch::IsInContactWithByRear(ControllableBatch &cb) +{ + if (((GetPosition() - GetLength()) - cb.GetPosition()) < PRF::prf.Min_Err()) + return (1); + else + return (0); +} + +//------------------------------------------------------------------------------ +// It sets the function to be applied in the evolution +//------------------------------------------------------------------------------ +void ControllableBatch::SetEvolveFunction(EvolveFunction _func) +{ + evolvefunction = _func; +} + +//------------------------------------------------------------------------------ +// It calls the evolution function of the controllable batch +//------------------------------------------------------------------------------ +void ControllableBatch::Evolve(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + if(evolvefunction == NULL) + return; + + (this->*evolvefunction)(_stime, tbp, pcb, ncb); + evolvefunction = NULL; +} + +//------------------------------------------------------------------------------ +// It applies the free behaviour at this controllable batch +//------------------------------------------------------------------------------ +void ControllableBatch::EvolveInFreeBehaviour(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + double move = (speed * _stime->StepTime()); + + if ((position == 0.0) && (length == 0.0)){ //new batch, input in free behaviour + length = move; + position = move; + } + else{ + if ((tbp->GetLength() - position) < PRF::prf.Min_Err()){ + length = length - move; + position = tbp->GetLength(); + } + else{ + position = position + move; + } + } +} + +//------------------------------------------------------------------------------ +// It applies the output in congestion behaviour at this controllable batch +//------------------------------------------------------------------------------ +void ControllableBatch::EvolveInCongestingOutputBehaviour(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + double downflow = tbp->GetOutputTransitonsFlow(); + double congestiondensity = tbp->GetCongestionDensity(); + + length = length - ((downflow/density) * _stime->StepTime()); +} + + +//------------------------------------------------------------------------------ +// It applies the free to congestion behaviour (congestion batch case) at this controllable batch +//------------------------------------------------------------------------------ +void ControllableBatch::EvolveInFreeToCongestingBehaviourCongBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + double vr = ncb->GetSpeed(); + double dr = ncb->GetDensity(); + double downflow = tbp->GetOutputTransitonsFlow(); + double drp = density; + + length = (((vr * dr) - downflow) / (drp - dr)) *_stime->StepTime(); +} + +//------------------------------------------------------------------------------ +// It applies the free to congestion behaviour (free batch case) at this controllable batch +//------------------------------------------------------------------------------ +void ControllableBatch::EvolveInFreeToCongestingBehaviourFreeBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + double vr = speed; + double dr = density; + double downflow = tbp->GetOutputTransitonsFlow(); + double drp = pcb->GetDensity(); + + position = position + ((downflow - vr * dr) / (drp - dr)) *_stime->StepTime(); + + length = length + ((downflow - vr * drp) / (drp - dr)) *_stime->StepTime(); +} + +//------------------------------------------------------------------------------ +// It applies the free to congestion behaviour to this batch in the middle of the place with +// contact with another batch (congestion batch case) +//------------------------------------------------------------------------------ +void ControllableBatch::EvolveInFreeToCongestingBehaviourMiddlePlaceWithContactCongBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + double vrp = speed; + double vr = ncb->GetSpeed(); + double drp = density; + double dr = ncb->GetDensity(); + + position = position + vrp *_stime->StepTime(); + + length = (dr / (dr - drp)) * (vrp - vr) *_stime->StepTime(); +} + +//------------------------------------------------------------------------------ +// It applies the free to congestion behaviour to this batch in the middle of the place with +// contact with another batch (free batch case) +//------------------------------------------------------------------------------ +void ControllableBatch::EvolveInFreeToCongestingBehaviourMiddlePlaceWithContactFreeBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + double vrp = pcb->GetSpeed(); + double vr = speed; + double drp = pcb->GetDensity(); + double dr = density; + + position = position + ((vrp*drp - vr*dr) / (drp - dr)) * _stime->StepTime(); + +// length = length - (drp / (dr - drp)) * (vrp - vr) * _stime->StepTime(); + length = length + (((vrp*drp) - vr * drp) / (drp - dr)) *_stime->StepTime(); +} + +//------------------------------------------------------------------------------ +// It applies the uncongestion behaviour to an output batch +//------------------------------------------------------------------------------ +void ControllableBatch::EvolveInUncongestingOutputBehaviour(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + double Vi = tbp->GetInstantaneousSpeed(); + + length = length - Vi * _stime->StepTime(); +} + +//------------------------------------------------------------------------------ +// It applies the uncongestion to free behaviour to this batch in the middle of the place (congestion batch case) +//------------------------------------------------------------------------------ +void ControllableBatch::EvolveInUncongestingToFreeBehaviourCongBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + double Vi = tbp->GetInstantaneousSpeed(); + double d_cri = tbp->GetCriticalDensity(); + double vr = speed; + double dr = density; + + position = position + ((Vi*d_cri) - (vr*dr)) / (d_cri-dr) * _stime->StepTime(); + length = length - ((Vi - vr) * d_cri / (dr - d_cri)) * _stime->StepTime(); +} + +//------------------------------------------------------------------------------ +// It applies the uncongestion to free behaviour to this batch in the middle of the place (Free batch case) +//------------------------------------------------------------------------------ +void ControllableBatch::EvolveInUncongestingToFreeBehaviourFreeBatch(Simtime *_stime, TriangularBatchPlace *tbp, ControllableBatch *pcb, ControllableBatch *ncb) +{ + double Vi = tbp->GetInstantaneousSpeed(); + double d_cri = tbp->GetCriticalDensity(); + double vr = ncb->GetSpeed(); + double dr = ncb->GetDensity(); + + position = position + Vi * _stime->StepTime(); + length = ((Vi - vr) * dr / (dr - d_cri)) * _stime->StepTime(); +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void ControllableBatch::Print(ostream &fout) +{ + fout << " (" << length << ", " << density << ", " << position << ", " << speed << ") - State: " << GetStateName() << " - Behaviour: " << GetBehaviourName() << endl; +} + +//------------------------------------------------------------------------------ +// Write +//------------------------------------------------------------------------------ +void ControllableBatch::Write(ostream &fout) +{ + fout << " (" << length << ", " << density << ", " << position << ", " << speed << ") - State: " << GetStateName() << " - Behaviour: " << GetBehaviourName() << endl; +} diff --git a/src/bpn/discreteplace.cpp b/src/bpn/discreteplace.cpp new file mode 100644 index 0000000..89d8990 --- /dev/null +++ b/src/bpn/discreteplace.cpp @@ -0,0 +1,233 @@ +//====================================================================================// +// // +// Discrete place classes inherit of place class // +// // +//====================================================================================// +// This File: discreteplace.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Discrete Place class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +DiscretePlace::DiscretePlace():Place() +{ + reservedmarks = 0; + nonreservedmarks = 0; +} + +//------------------------------------------------------------------------------ +// Named Constructor +//------------------------------------------------------------------------------ +DiscretePlace::DiscretePlace(simuleau_name _name):Place(_name) +{ + reservedmarks = 0; + nonreservedmarks = 0; +} + + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +DiscretePlace::~DiscretePlace() +{ + +} + + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void DiscretePlace::Copy(const DiscretePlace * _place) +{ + TransferNode(_place); + + marks = _place->marks; + initialmarks = _place->initialmarks; + steadymarks = _place->steadymarks; + reservedmarks = _place->reservedmarks; + nonreservedmarks = _place->nonreservedmarks; + + conflict = _place->conflict; + structuralconflict = _place->structuralconflict; + +} + +//------------------------------------------------------------------------------ +// It set the initial marking of the place +//------------------------------------------------------------------------------ +void DiscretePlace::SetInitialMarking(int m) +{ + marks = initialmarks = m; + reservedmarks = 0; + nonreservedmarks = m; +} + +//------------------------------------------------------------------------------ +// It set the steady marking of the place +//------------------------------------------------------------------------------ +void DiscretePlace::SetSteadyMarking(int m) +{ + steadymarks = m; +} + +//------------------------------------------------------------------------------ +// It changes the place marks +//------------------------------------------------------------------------------ +void DiscretePlace::ChangeMarks(int m) +{ + marks = nonreservedmarks = m; + if (abs(m) < PRF::prf.Min_Err()){ + marks = nonreservedmarks = 0; + } +} + + +//------------------------------------------------------------------------------ +// It reserves the place marks +//------------------------------------------------------------------------------ +void DiscretePlace::ReserveMarks(int m) +{ + reservedmarks+=m; + nonreservedmarks = marks - reservedmarks; +} + + +//------------------------------------------------------------------------------ +// It removes the reserved marks in the place +//------------------------------------------------------------------------------ +void DiscretePlace::RemoveReservedMarks(int m) +{ + reservedmarks-=m; + marks = nonreservedmarks + reservedmarks; +} + +//------------------------------------------------------------------------------ +// It adds the marks to the place +//------------------------------------------------------------------------------ +void DiscretePlace::AddMarks(int m) +{ + nonreservedmarks += m; + marks += m; +} + +//------------------------------------------------------------------------------ +// Compute the state of the discrete place +//------------------------------------------------------------------------------ +void DiscretePlace::ComputeState() +{ + int j = 0; + + if (reservedmarks != 0){ + state = 0.5; + } + else{ + if (GetNumberOfOutputArcs() == 0){ + state = 1.0; + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0){ + if (nonreservedmarks < outputarcs[i]){ +// cout << "nonreservedmarks: " << nonreservedmarks << " outputarcs: " << outputarcs[i] << endl; + j++; + } + } + } + if (j == 0) + state = 1.0; + else + state = 0.0; + } + } +} + +//------------------------------------------------------------------------------ +// It verifies effectif conflits +//------------------------------------------------------------------------------ +int DiscretePlace::VerifyConflict() +{ + int necessarymarks = 0; + int numberoftransitionsinconflict = 0; + Transition *t; + + conflict = 0; + + if (structuralconflict){ + if (GetNumberOfOutputArcs() != 0){ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ + t = outputnodes[i]; + //t = simulation->sbpn->GetTransition(i); + if ((t->GetState()==1) && (t->IsA() == Discrete_tr)) { + necessarymarks+= outputarcs[i]; + numberoftransitionsinconflict++; + } + } + } + +/* Ancienne version a conserver + represente le vrai conflit effectif + c-a-d au moins 2 trans aval validees + avec marquage de la place necessaire pour les franchissements + mais actuellement le simulateur ne peut traiter ce cas !!!! + if (marqueNecessaire <= marqueNonReservee) + conflitEffec =0; + else + conflitEffec =1; + */ + + if (numberoftransitionsinconflict > 1){ + if (necessarymarks <= nonreservedmarks) + conflict = 0; + else + conflict = 1; + + return (conflict); + } + } + } + return (0); +} + + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void DiscretePlace::Print(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Discrete" << endl; + fout << " Marks: " << marks << endl; + fout << " Initial Marks: " << initialmarks << endl; + if (steadymarks != 0) + fout << " Steady Marks: " << steadymarks << endl; + fout << " Reserved Marks: " << reservedmarks << endl; + fout << " Non Reserved Marks: " << nonreservedmarks << endl; + fout << " Arcs: " << endl; + PrintArcs(fout); +} + +//------------------------------------------------------------------------------ +// Write +//------------------------------------------------------------------------------ +void DiscretePlace::Write(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Discrete" << endl; + fout << " Marks: " << marks << endl; + fout << " Reserved Marks: " << reservedmarks << endl; +// if (steadymarks != 0) +// fout << " Steady Marks: " << steadymarks << endl; +} diff --git a/src/bpn/discretetransition.cpp b/src/bpn/discretetransition.cpp new file mode 100644 index 0000000..8143ed1 --- /dev/null +++ b/src/bpn/discretetransition.cpp @@ -0,0 +1,225 @@ +//====================================================================================// +// // +// Discrete transition classes inherit of transition class // +// // +//====================================================================================// +// This File: discretetransition.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Discrete Transition class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +DiscreteTransition::DiscreteTransition() +{ + +} + +//------------------------------------------------------------------------------ +// Initialized Constructor +//------------------------------------------------------------------------------ +DiscreteTransition::DiscreteTransition(simuleau_name _name, double _time, double _steadytime):Transition(_name) +{ + time = _time; + steadytime = _steadytime; + enableddate = -_time; + +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +DiscreteTransition::~DiscreteTransition() +{ + +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void DiscreteTransition::Copy(const DiscreteTransition *_transition) +{ + TransferNode(_transition); + time = _transition->time; // transition time + steadytime = _transition->steadytime; // transition steady time + enableddate = _transition->enableddate; // enabled date + firingquantity = new FiringQuantity; + firingquantity->Copy(_transition->firingquantity); +} + +//------------------------------------------------------------------------------ +// Initializes enabled date +//------------------------------------------------------------------------------ +void DiscreteTransition::InitEnabledDate() +{ + enableddate = -1.0; +} + + +//------------------------------------------------------------------------------ +// Set enabled date +//------------------------------------------------------------------------------ +void DiscreteTransition::SetEnabledDate(double _date) +{ + enableddate = _date; +} + +//------------------------------------------------------------------------------ +// Reserve marks in input places of the transition +//------------------------------------------------------------------------------ +void DiscreteTransition::ReserveMarksInputPlaces() +{ + double weight; + Place *p; + + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ + weight = inputarcs[i]; +// p = simulation->sbpn->GetPlace(i); + p = inputnodes[i]; + + switch (p->IsA()){ + case Discrete_pl : ((DiscretePlace*)p)->ReserveMarks((int)weight); +// cout << "\n\n\n discrete \n\n\n"; + break; + case Continuous_pl : ((ContinuousPlace*)p)->ReserveMarks(weight); +// cout << "\n\n\n continuous \n\n\n"; + + break; + } + } + } +} + + +//------------------------------------------------------------------------------ +// Get time +//------------------------------------------------------------------------------ +double DiscreteTransition::GetTime() +{ + return (time); +} + +//------------------------------------------------------------------------------ +// Get enabled date +//------------------------------------------------------------------------------ +double DiscreteTransition::GetEnabledDate() +{ + return (enableddate); +} + + +//------------------------------------------------------------------------------ +// Compute states +//------------------------------------------------------------------------------ +void DiscreteTransition::ComputeState() +{ + double transstate = 1.0; // enabled + double placestate; + Place *p; + + if (GetNumberOfInputArcs() == 0){ + if ((enableddate + time) > simulation->stime->GetCurrentDate()){ + state = 0.5; // enable transition but not fired + } + else { + state = 1.0; // transition not enable + } + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ +// p = simulation->sbpn->GetPlace(i); + p = inputnodes[i]; + placestate = p->GetState(); +// cout << "\n==========================\nplace: " << placestate << "\n==========================\n"; + transstate = min(transstate, placestate); + } + } + state = transstate; + } +// cout << "\n==========================\nState: " << state << "\n==========================\n"; +} + +//------------------------------------------------------------------------------ +// Fire transition +//------------------------------------------------------------------------------ +void DiscreteTransition::WalkThrough(double duration) +{ + if (duration < 0.0) + FireDiscreteTransition(); +} + +//------------------------------------------------------------------------------ +// Fire discrete transition +//------------------------------------------------------------------------------ +void DiscreteTransition::FireDiscreteTransition() +{ + double weight; + Place *p; + + // remove marks of the input places + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ + weight = inputarcs[i]; +// p = simulation->sbpn->GetPlace(i); + p = inputnodes[i]; + + switch (p->IsA()){ + case Discrete_pl : ((DiscretePlace*)p)->RemoveReservedMarks((int)weight); +// cout << "\n\n\n discrete \n\n\n"; + break; + case Continuous_pl : ((ContinuousPlace*)p)->RemoveReservedMarks(weight); +// cout << "\n\n\n continuous \n\n\n"; + + break; + } + } + } + + // add marks of the output places + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ + weight = outputarcs[i]; +// p = simulation->sbpn->GetPlace(i); + p = outputnodes[i]; + + switch (p->IsA()){ + case Discrete_pl : ((DiscretePlace*)p)->AddMarks((int)weight); +// cout << "\n\n\n discrete \n\n\n"; + break; + case Continuous_pl : ((ContinuousPlace*)p)->AddMarks(weight); +// cout << "\n\n\n continuous \n\n\n"; + + break; + } + } + } + InitEnabledDate(); +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void DiscreteTransition::Print(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Discrete" << endl; + fout << " Time: " << time << endl; + if (steadytime!=0.0) + fout << " Steady Time: " << time << endl; + + fout << " Arcs: " << endl; + PrintArcs(fout); +} + diff --git a/src/bpn/firingquantity.cpp b/src/bpn/firingquantity.cpp new file mode 100644 index 0000000..f76723a --- /dev/null +++ b/src/bpn/firingquantity.cpp @@ -0,0 +1,98 @@ +//====================================================================================// +// // +// FiringQuantity class // +// // +//====================================================================================// +// This File: flow.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 29/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 29/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +FiringQuantity::FiringQuantity() +{ + firingquantity=steadyfiringquantity=currentfiringquantity = 0.0; +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +FiringQuantity::~FiringQuantity() +{ + //dtor +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void FiringQuantity::Copy(const FiringQuantity *_firingquantity) +{ + steadyfiringquantity = _firingquantity->steadyfiringquantity; + currentfiringquantity = _firingquantity->currentfiringquantity; +} + +//------------------------------------------------------------------------------ +// Set up all firingquanties +//------------------------------------------------------------------------------ +void FiringQuantity::SetAllFiringQuantities(double _firingquantity) +{ + steadyfiringquantity=currentfiringquantity = _firingquantity; +} + +//------------------------------------------------------------------------------ +// Set up the intial flow +//------------------------------------------------------------------------------ +//void Flow::SetInitialFlow(double _flow) +//{ +// initialflow = _flow; +//} + +//------------------------------------------------------------------------------ +// Set up the current firingquantity +//------------------------------------------------------------------------------ +void FiringQuantity::SetCurrentFiringQuantity(double _firingquantity) +{ + currentfiringquantity= _firingquantity; +} + + +//------------------------------------------------------------------------------ +// Set up the steady firingquantity +//------------------------------------------------------------------------------ +void FiringQuantity::SetSteadyFiringQuantity(double _firingquantity) +{ + steadyfiringquantity= _firingquantity; +} + +//------------------------------------------------------------------------------ +// Return the current firing quantity +//------------------------------------------------------------------------------ +double FiringQuantity::GetCurrentFiringQuantity() +{ + return (currentfiringquantity); +} + +//------------------------------------------------------------------------------ +// Return the steady firing quantity +//------------------------------------------------------------------------------ +double FiringQuantity::GetSteadyFiringQuantity() +{ + return (steadyfiringquantity); +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void FiringQuantity::Print(ostream &fout) +{ + fout << " Current : " << currentfiringquantity << endl; + // fout << " Initial : " << initialflow << endl; + if (steadyfiringquantity!=-1.0) + fout << " Steady : " << steadyfiringquantity << endl << endl; + +} diff --git a/src/bpn/firingquantity.h b/src/bpn/firingquantity.h new file mode 100644 index 0000000..a614427 --- /dev/null +++ b/src/bpn/firingquantity.h @@ -0,0 +1,45 @@ +//====================================================================================// +// // +// Firingquantity class // +// // +//====================================================================================// +// This File: firingquantity.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 29/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 29/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef FIRINGQUANTITY_H +#define FIRINGQUANTITY_H + +class FiringQuantity +{ + public: + FiringQuantity(); + virtual ~FiringQuantity(); + + void Copy(const FiringQuantity *_firingquantity); + + // input functions + void SetAllFiringQuantities(double _firingquantity); + void SetCurrentFiringQuantity(double _firingquantity); + void SetSteadyFiringQuantity(double _firingquantity); + + + // output functions + double GetCurrentFiringQuantity(); + double GetSteadyFiringQuantity(); + + + //print + void Print(ostream &fout); + + protected: + double firingquantity; + double currentfiringquantity; + double steadyfiringquantity; + + private: +}; + +#endif // FIRINGQUANTITY_H diff --git a/src/bpn/flow.cpp b/src/bpn/flow.cpp new file mode 100644 index 0000000..399d308 --- /dev/null +++ b/src/bpn/flow.cpp @@ -0,0 +1,136 @@ +//====================================================================================// +// // +// Flow class // +// // +//====================================================================================// +// This File: flow.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 29/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 29/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Flow::Flow() +{ + maximumflow = theoreticalflow = currentflow = initialflow = steadyflow = -1.0; +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Flow::~Flow() +{ + //dtor +} + + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void Flow::Copy(const Flow *_flow) +{ + maximumflow = _flow->maximumflow; + theoreticalflow = _flow->theoreticalflow; + currentflow = _flow->currentflow; + initialflow = _flow->initialflow; + steadyflow = _flow->steadyflow; + +} + +//------------------------------------------------------------------------------ +// Set up all flows +//------------------------------------------------------------------------------ +void Flow::SetAllFlows(double _flow) +{ + maximumflow = theoreticalflow = currentflow = initialflow = steadyflow = _flow; +} + +//------------------------------------------------------------------------------ +// Set up the intial flow +//------------------------------------------------------------------------------ +void Flow::SetInitialFlow(double _flow) +{ + initialflow = _flow; +} + +//------------------------------------------------------------------------------ +// Set up the current flow +//------------------------------------------------------------------------------ +void Flow::SetCurrentFlow(double _flow) +{ + currentflow = _flow; +} + +//------------------------------------------------------------------------------ +// Set up the theoretical flow +//------------------------------------------------------------------------------ +void Flow::SetTheoreticalFlow(double _flow) +{ + theoreticalflow = _flow; +} + +//------------------------------------------------------------------------------ +// Set up the theoretical flow +//------------------------------------------------------------------------------ +void Flow::SetMaximumFlow(double _flow) +{ + maximumflow = _flow; +} + +//------------------------------------------------------------------------------ +// Set up the steady flow +//------------------------------------------------------------------------------ +void Flow::SetSteadyFlow(double _flow) +{ + steadyflow = _flow; +} + +//------------------------------------------------------------------------------ +// Return the current flow +//------------------------------------------------------------------------------ +double Flow::GetCurrentFlow() +{ + return (currentflow); +} + +//------------------------------------------------------------------------------ +// Return the theoretical flow +//------------------------------------------------------------------------------ +double Flow::GetTheoreticalFlow() +{ + return (theoreticalflow); +} + +//------------------------------------------------------------------------------ +// Return the maximum flow +//------------------------------------------------------------------------------ +double Flow::GetMaximumFlow() +{ + return (maximumflow); +} + +//------------------------------------------------------------------------------ +// Return the steady flow +//------------------------------------------------------------------------------ +double Flow::GetSteadyFlow() +{ + return (steadyflow); +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Flow::Print(ostream &fout) +{ + fout << " Maximum : " << maximumflow << endl; + fout << " Theoretical : " << theoreticalflow << endl; + fout << " Current : " << currentflow << endl; + fout << " Initial : " << initialflow << endl; + if (steadyflow!=-1.0) + fout << " Steady : " << steadyflow << endl << endl; + +} diff --git a/src/bpn/flow.h b/src/bpn/flow.h new file mode 100644 index 0000000..a86a2b2 --- /dev/null +++ b/src/bpn/flow.h @@ -0,0 +1,52 @@ +//====================================================================================// +// // +// Flow class // +// // +//====================================================================================// +// This File: flow.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 29/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 29/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef FLOW_H +#define FLOW_H + +class Flow +{ + public: + Flow(); + virtual ~Flow(); + + void Copy(const Flow *_flow); + + // input functions + void SetAllFlows(double _flow); + void SetInitialFlow(double _flow); + void SetCurrentFlow(double _flow); + void SetTheoreticalFlow(double _flow); + void SetMaximumFlow(double _flow); + void SetSteadyFlow(double _flow); + + + // output functions + double GetCurrentFlow(); + double GetTheoreticalFlow(); + double GetMaximumFlow(); + double GetSteadyFlow(); + + + //print + void Print(ostream &fout); + + protected: + double maximumflow; + double theoreticalflow; + double currentflow; + double initialflow; + double steadyflow; + + private: +}; + +#endif // FLOW_H diff --git a/src/bpn/node.cpp b/src/bpn/node.cpp new file mode 100644 index 0000000..305ea8c --- /dev/null +++ b/src/bpn/node.cpp @@ -0,0 +1,274 @@ +//====================================================================================// +// // +// Node class // +// // +//====================================================================================// +// This File: node.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 21/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 21/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Node::Node() +{ + numberofarcs = 0; // number of input arcs to this node + inputarcs = NULL; // array of input arcs + inputnodes = NULL; // array of input nodes + outputarcs = NULL; // array of output arcs + outputnodes = NULL; // array of output nodes + + strcpy(name,""); // node name + state = No_state; // node state + +} + +//------------------------------------------------------------------------------ +// Named constructor +//------------------------------------------------------------------------------ +Node::Node(simuleau_name _name) +{ + numberofarcs = 0; // number of output arcs from this node + inputarcs = NULL; // array of input arcs + inputnodes = NULL; // array of input nodes + outputarcs = NULL; // array of output arcs + outputnodes = NULL; // array of output nodes + + strcpy(name,_name); // node name + state = 0.0; // node state +} + + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Node::~Node() +{ + if (inputarcs) + delete [] inputarcs; + if (inputnodes) + delete [] inputnodes; + if (outputarcs) + delete [] outputarcs; + if (outputnodes) + delete [] outputnodes; +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void Node::Copy(const Node *_node) +{ + strcpy(name,_node->name); // node name + state = _node->state; // node state + numberofarcs = _node->numberofarcs; // number of arcs (places or transitions) + + if (numberofarcs > 0){ + inputarcs = new double [numberofarcs]; + inputnodes = new Node* [numberofarcs]; + for (int i=0; i<numberofarcs; i++){ + inputarcs[i] = _node->inputarcs[i]; // 0 means this arc is not used + inputnodes[i] = _node->inputnodes[i]; + } + + outputarcs = new double [numberofarcs]; + outputnodes = new Node* [numberofarcs]; + for (int i=0; i<numberofarcs; i++){ + outputarcs[i] = _node->outputarcs[i]; // 0 means this arc is not used + outputnodes[i] = _node->outputnodes[i]; + } + } +} + + +//------------------------------------------------------------------------------ +// It alloc the array of input/output arcs +//------------------------------------------------------------------------------ +int Node::AllocArcs(int n) +{ + numberofarcs = n; + inputarcs = new double [n]; + inputnodes = new Node* [n]; + for (int i=0; i<n; i++){ + inputarcs[i] = 0; // 0 means this arc is not used + inputnodes[i] = NULL; + } + + outputarcs = new double [n]; + outputnodes = new Node* [n]; + for (int i=0; i<n; i++){ + outputarcs[i] = 0; // 0 means this arc is not used + outputnodes[i] = 0; + } +} + +//------------------------------------------------------------------------------ +// It adds an input arc in the positin pos with weight +//------------------------------------------------------------------------------ +int Node::AddInputArc(int pos, double weight) +{ + inputarcs[pos] = weight; +} + +//------------------------------------------------------------------------------ +// It adds an output arc in the positin pos with weight +//------------------------------------------------------------------------------ +int Node::AddOutputArc(int pos, double weight) +{ + outputarcs[pos] = weight; +} + +//------------------------------------------------------------------------------ +// set input node pointes +//------------------------------------------------------------------------------ +int Node::AddInputNodes(Node **nodes) +{ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0.0) + inputnodes[i] = nodes[i]; + else + inputnodes[i] = NULL; + } +} + + + +//------------------------------------------------------------------------------ +// set output node pointes +//------------------------------------------------------------------------------ +int Node::AddOutputNodes(Node **nodes) +{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0.0) + outputnodes[i] = nodes[i]; + else + outputnodes[i] = NULL; + } +} + +//------------------------------------------------------------------------------ +// set node state +//------------------------------------------------------------------------------ +void Node::SetState(double _state) +{ + state = _state; +} + + +//------------------------------------------------------------------------------ +// It get the node name +//------------------------------------------------------------------------------ +char* Node::GetName() +{ + return (name); +} + +//------------------------------------------------------------------------------ +// It get the current node state +//------------------------------------------------------------------------------ +double Node::GetState() +{ + return (state); +} + +//------------------------------------------------------------------------------ +// get the number of input arc different of 0 +//------------------------------------------------------------------------------ +int Node::GetNumberOfInputArcs() +{ + int n = 0; + + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0) + n++; + } + return (n); +} + +//------------------------------------------------------------------------------ +// get the number of Output arc different of 0 +//------------------------------------------------------------------------------ +int Node::GetNumberOfOutputArcs() +{ + int n = 0; + + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0) + n++; + } + return (n); +} + +//------------------------------------------------------------------------------ +// get the weight of an input arc +//------------------------------------------------------------------------------ +double Node::GetWeightOfInputArc(int _arc) +{ + return (inputarcs[_arc]); +} + +//------------------------------------------------------------------------------ +// get the weight of an output arc +//------------------------------------------------------------------------------ +double Node::GetWeightOfOutputArc(int _arc) +{ + return (outputarcs[_arc]); +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Node::Print(ostream &fout) +{ + fout << "Name: " << name << endl; + PrintArcs(fout); +} + + +//------------------------------------------------------------------------------ +// Print arcs +//------------------------------------------------------------------------------ +void Node::PrintArcs(ostream &fout) +{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i]){ + fout << " to " << outputnodes[i]->GetName() << " : " << outputarcs[i] << endl; + } + } + + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i]) + fout << " from " << inputnodes[i]->GetName() << " : " << inputarcs[i] << endl; + } + fout << endl; +} + +//------------------------------------------------------------------------------ +// Transfer node informations +//------------------------------------------------------------------------------ +void Node::TransferNode(const Node *_node) +{ + strcpy(name,_node->name); // node name + state = _node->state; // node state + numberofarcs = _node->numberofarcs; // number of arcs (places or transitions) + + if (numberofarcs > 0){ + inputarcs = new double [numberofarcs]; + inputnodes = new Node* [numberofarcs]; + for (int i=0; i<numberofarcs; i++){ + inputarcs[i] = _node->inputarcs[i]; // 0 means this arc is not used + inputnodes[i] = _node->inputnodes[i]; + } + + outputarcs = new double [numberofarcs]; + outputnodes = new Node* [numberofarcs]; + for (int i=0; i<numberofarcs; i++){ + outputarcs[i] = _node->outputarcs[i]; // 0 means this arc is not used + outputnodes[i] = _node->outputnodes[i]; + } + } +} diff --git a/src/bpn/node.h b/src/bpn/node.h new file mode 100644 index 0000000..ac89f2c --- /dev/null +++ b/src/bpn/node.h @@ -0,0 +1,61 @@ +//====================================================================================// +// // +// Node class // +// // +//====================================================================================// +// This File: node.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 21/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 21/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef NODE_H +#define NODE_H + +class Node +{ + public: + Node(); + Node(simuleau_name _name); + virtual ~Node(); + + void Copy(const Node *_node); + + // input functions + int AllocArcs(int n); // number of input/output arcs and nodes + int AddInputArc(int pos, double weight); // add input arc in the position pos + int AddOutputArc(int pos, double weight); // add output arc in the position pos + int AddInputNodes(Node **nodes); // add input node pointers + int AddOutputNodes(Node **nodes); // add output node pointers + + void SetState(double _state); + + // output functions + char * GetName(); // get the node name + double GetState(); // get the current node state + int GetNumberOfInputArcs(); // get the number of input arc different of 0 + int GetNumberOfOutputArcs(); // get the number of output arc different of 0 + double GetWeightOfInputArc(int _arc); // Get the weight of an input arc + double GetWeightOfOutputArc(int _arc); // Get the weight of an output arc + + // print functions + virtual void Print(ostream &fout); // print node informations + void PrintArcs(ostream &fout); // print arcs + + protected: + int numberofarcs; // number of arcs to this node +// int numberofoutputarcs; // number of output arcs from this node + double *inputarcs; // array of input arcs + double *outputarcs; // array of output arcs + Node **inputnodes; // pointers to input nodes + Node **outputnodes; // pointers to output nodes + + simuleau_name name; // node name + double state; // node state + + void TransferNode(const Node *_node); + + private: +}; + +#endif // NODE_H diff --git a/src/bpn/place.cpp b/src/bpn/place.cpp new file mode 100644 index 0000000..375ce0d --- /dev/null +++ b/src/bpn/place.cpp @@ -0,0 +1,146 @@ +//====================================================================================// +// // +// Place classes inherit of node class // +// // +//====================================================================================// +// This File: place.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Place class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Place::Place() +{ + marks = 0; + initialmarks = 0; + steadymarks = -1; + + conflict = 0; + structuralconflict = 0; +} + +//------------------------------------------------------------------------------ +// Named Constructor +//------------------------------------------------------------------------------ +Place::Place(simuleau_name _name):Node(_name) +{ + marks = 0; + initialmarks = 0; + steadymarks = -1; + + conflict = 0; + structuralconflict = 0; +} + + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Place::~Place() +{ + //dtor +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void Place::Copy(const Place * _place) +{ + TransferNode(_place); + + marks = _place->marks; + initialmarks = _place->initialmarks; + steadymarks = _place->steadymarks; + + conflict = _place->conflict; + structuralconflict = _place->structuralconflict; +} + +//------------------------------------------------------------------------------ +// It set the initial marking of the place +//------------------------------------------------------------------------------ +void Place::SetInitialMarking(int m) +{ + marks = initialmarks = m; +} + +//------------------------------------------------------------------------------ +// It set the steady marking of the place +//------------------------------------------------------------------------------ +void Place::SetSteadyMarking(int m) +{ + steadymarks = m; +} + + +//------------------------------------------------------------------------------ +// It returns the current marks +//------------------------------------------------------------------------------ +int Place::GetMarks() +{ + return (marks); +} + +//------------------------------------------------------------------------------ +// It researches structural conflits +//------------------------------------------------------------------------------ +void Place::ResearchStructuralConflict() +{ + int numberofoutputarcs = GetNumberOfOutputArcs(); + + if(numberofoutputarcs <= 1) + structuralconflict = 0; + else + structuralconflict = numberofoutputarcs; +} + +//------------------------------------------------------------------------------ +// It returns structural conflits +//------------------------------------------------------------------------------ +int Place::GetStructuralConflict() +{ + return (structuralconflict); +} + +//------------------------------------------------------------------------------ +// It verifies effectif conflits +// returns 0 by default - Batch places don't have conflits +//------------------------------------------------------------------------------ +int Place::VerifyConflict() +{ + return (0); +} + + + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Place::Print(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Arcs: " << endl; + PrintArcs(fout); +} + +//------------------------------------------------------------------------------ +// Write +//------------------------------------------------------------------------------ +void Place::Write(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Marks: " << marks << endl; +// if (steadymarks != 0) +// fout << " Steady Marks: " << steadymarks << endl; +} diff --git a/src/bpn/place.h b/src/bpn/place.h new file mode 100644 index 0000000..74dfc35 --- /dev/null +++ b/src/bpn/place.h @@ -0,0 +1,367 @@ +//====================================================================================// +// // +// Place classes inherit of node class // +// // +//====================================================================================// +// This File: place.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef PLACE_H +#define PLACE_H +#include <simuleau.h> + +//====================================================================================// +// Generic place class // +//====================================================================================// +// Place class implements a generic place that will be used to implement all other // +// place classes (discrete, continuous, batch and triangular batch) that can compose // +// a Batch Petri Net. // +//====================================================================================// +class Place : public Node +{ + public: + Place(); + Place(simuleau_name _name); + virtual ~Place(); + + void Copy (const Place * _place); + virtual place_type IsA() {}; + + // input functions + virtual void SetInitialMarking(int m); + virtual void SetSteadyMarking(int m); + virtual void SetInitialMarking(double m){}; + virtual void SetSteadyMarking(double m){}; + virtual void AddBatchToInitialMarking(Batch &b){}; + virtual void AddBatchToSteadyMarking(Batch &b){}; + virtual void AddBatchToInitialMarking(ControllableBatch &b){}; + virtual void AddBatchToSteadyMarking(ControllableBatch &b){}; + + //simulation functions + virtual void ComputeState(){}; + int GetMarks(); + virtual void EvolveMarks(double _date){}; + virtual void ResearchStructuralConflict(); + virtual int GetStructuralConflict(); + virtual int VerifyConflict(); + + // print functions + virtual void Print(ostream &fout); + virtual void Write(ostream &fout); + + protected: + int marks; + int initialmarks; + int steadymarks; + int structuralconflict; + int conflict; + + private: +}; + + +//====================================================================================// +// Discrete place class // +//====================================================================================// +// Discrete place class is generally used to model control in BPN. // +// These place have a integer number of tokens. // +//====================================================================================// +class DiscretePlace : public Place +{ + public: + DiscretePlace(); + DiscretePlace(simuleau_name _name); + virtual ~DiscretePlace(); + + void Copy (const DiscretePlace * _place); + place_type IsA() {return Discrete_pl;}; + + + // input functions + void SetInitialMarking(int m); + void SetSteadyMarking(int m); + + //simulation functions + void ChangeMarks(int m); + void ReserveMarks(int m); + void RemoveReservedMarks(int m); + void AddMarks(int m); + + void ComputeState(); + + int VerifyConflict(); + + + // print functions + void Print(ostream &fout); + void Write(ostream &fout); + + protected: + int reservedmarks; + int nonreservedmarks; + + + private: +}; + + +//====================================================================================// +// Continuous place class // +//====================================================================================// +// These place have a real number of tokens. // +//====================================================================================// +class ContinuousPlace : public Place +{ + public: + ContinuousPlace(); + ContinuousPlace(simuleau_name _name); + virtual ~ContinuousPlace(); + + void Copy (const ContinuousPlace * _place); + virtual place_type IsA() {return Continuous_pl;}; + + // input functions + void SetInitialMarking(double m); + void SetSteadyMarking(double m); + + //output functions + //double GetOutputTransitonsFlow(); + + //simulation function + double GetMarks(); + double GetInitialMarks(); + double GetSteadyMarks(); + void ChangeMarks(double m); + void ReduceMarks(double m); + void ReserveMarks(double m); + void RemoveReservedMarks(double m); + void AddMarks(double m); + void ComputeState(); + void EvolveMarks(double _date); + void VerifyMarks(); + + int VerifyConflict(); + + double PlaceIsFed(); + virtual int IsEqualSteadyQuantity(); + virtual int IsGreaterThanSteadyQuantity(); + virtual int IsLessThanSteadyQuantity(); + virtual int IsSteadyMarkingReached(); + virtual int IsSteadyMarkingReachedandInputOutputTransitionBelongTz(); + double ComputeFlowFedPlace(ContinuousTransition *ct); + double GetCPEEvent(); + double GetDTEEvent(); + double GetPSQEvent(); + + // print functions + void Print(ostream &fout); + void Write(ostream &fout); + + + protected: + double marks; + double initialmarks; + double steadymarks; + double reservedmarks; + double nonreservedmarks; + + + double ComputeDateDTEEvent(DiscreteTransition *t, double weight); + double ComputeInputFlow(); + + private: +}; + +//====================================================================================// +// Batch place class // +//====================================================================================// +// Batch places model a transfer of batch entities over a space/temporal place // +// These place have batches. // +//====================================================================================// +class BatchPlace : public Place +{ + public: + BatchPlace(); + BatchPlace(simuleau_name _name, double _speed, double _density, double _length); + virtual ~BatchPlace(); + + void Copy (const BatchPlace * _place); + virtual place_type IsA() {return Batch_pl;}; + + // input functions + void AddBatchToInitialMarking(Batch &b); + void AddBatchToSteadyMarking(Batch &b); + void AddBatchToMarking(Batch &b); + void ChangeMarks(list<Batch> *lb); + void SetSpeed(double _speed); + void SetMaxSpeed(double _maxspeed); + void SetDensity(double _density); + void SetLength(double _length); + + // output functions + double GetSpeed(); + double GetMaxSpeed(); + double GetInstantaneousSpeed(); + double GetDensity(); + double GetLength(); + double GetOutputFlow(); + double GetInitialQuantity(); + double GetFreeSteadyQuantity(); // q_i^{f,s} + double GetSteadyQuantity(); + list<Batch>* GetInitialMarking(); + list<Batch>* GetSteadyMarking(); + list<Batch>* GetMarking(); + int GetBehaviour(); + double GetFlowOfOutputTransition(); + double GetInputTransitonsFlow(); + double GetOutputTransitonsFlow(); + double GetSteadyPlaceFlow(); // \phi_i^s The steady flow in a batch place. + double GetSteadyDensity(); // d_i^s the steady density of a batch place. + + + virtual int HasOutputBatch(); + Batch * GetOutputBatch(); + virtual double GetDensityOutputBatch(); + + virtual int IsFull(); + virtual int IsEqualSteadyQuantity(); + virtual int IsGreaterThanSteadyQuantity(); + virtual int IsLessThanSteadyQuantity(); + virtual int IsSteadyMarkingReached(); + virtual int IsSteadyMarkingQuantityReachedandInputOutputTransitionBelongTz(); + virtual int IsHoldSteadyPlaceFlowUntilSteadyState(); + + + //simulation functions + virtual void ComputeState(); + + virtual int CreateBatches(); + virtual void MergeBatches(); + virtual void DestructBatches(); + virtual void ComputeQuantities(); +// virtual void ComputeTwoTypesSteadyQuantities(); // the steady marking quantity in a free part and accumulated part. + + virtual void ComputeBehaviour(); + virtual void EvolveMarks(double _date); + + virtual double GetBOBEvent(); + virtual double GetDOBEvent(); + virtual double GetBBDEvent(); + virtual double GetTBMEvent(); + virtual double GetPSQEvent(); + + + // print functions + virtual void Print(ostream &fout); + virtual void Write(ostream &fout); + + protected: + int behaviour; + int formalisation; + list<Batch> *marks; + list<Batch> *initialmarks; + list<Batch> *steadymarks; + double density; + double maxspeed; + double speed; + double instantaneousspeed; + double length; + double quantity; + double steadyquantity; + + void EvolveInFreeBehaviour(Simtime *st); // RL + void EvolveInAccumulatedOutputBehaviour(Simtime *st); // SA + void EvolveInPartiallyAccumulatedBehaviour(Simtime *st); //RAP + void EvolveInFreeToAccumulatedBehaviour(Simtime *st);// RLA + + private: +}; + +//====================================================================================// +// Triangular Batch place class // +//====================================================================================// +// Triangular batch places are a special kind of batch places dedicated to model // +// trafic route systems. The batches in batch place must follow a triangular fundamen-// +// tal diagram issue of the trafic route model. // +// These place have triangular batches. // +//====================================================================================// +class TriangularBatchPlace : public BatchPlace +{ + public: + TriangularBatchPlace(); + TriangularBatchPlace(simuleau_name _name, double _speed, double _density, double _length, double _flow); + virtual ~TriangularBatchPlace(); + + void Copy (const TriangularBatchPlace * _place); + place_type IsA() {return Triangular_pl;}; + + + // input functions + void AddBatchToInitialMarking(ControllableBatch &b); + void AddBatchToSteadyMarking(ControllableBatch &b); + void AddBatchToMarking(ControllableBatch &b); + void SetFlow(double _flow); + void SetMaxFlow(double _flow); + + // output functions + double GetFlow(); + double GetMaxFlow(); + + int IsFull(); + int HasOutputBatch(); + ControllableBatch* GetOutputControllableBatch(); + + double GetCriticalDensity(); + double GetDensityOutputBatch(); + double GetSpeedOutputBatch(); + double GetFlowOutputBatch(); + double GetCongestionDensity(); + double GetPropagationSpeed(); + + + //simulation functions + void ComputeState(); + + int CreateBatches(); + void MergeBatches(); + void DestructBatches(); + + void ComputeBehaviour(); + void SetAndRecomputeSpeed(double newspeed); + void SetBehaviourFunctions(); //precomputebehaviour + void SetFunctionFreeBatch(list<ControllableBatch>::iterator cbi, int i); + void SetFunctionCongestedBatch(list<ControllableBatch>::iterator cbi, int i); + void SetFunctionUncongestingBatch(list<ControllableBatch>::iterator cbi, int i); + void EvolveMarks(double _date); + void EvolveControllableBatch(list<ControllableBatch>::iterator cbi, double _date); + + double GetBOBEvent(); + double GetDOBEvent(); + double GetBBDEvent(); + double GetTBMEvent(); + double GetBMOBEvent(); + double GetOBDEvent(); + double GetBDEvent(); + double GetBBFEvent(); + + + + // print functions + void Print(ostream &fout); + void Write(ostream &fout); + + protected: + list<ControllableBatch> *marks; + list<ControllableBatch> *initialmarks; + list<ControllableBatch> *steadymarks; + double maxflow; + double flow; + + private: +}; + + +#endif // PLACE_H diff --git a/src/bpn/transition.cpp b/src/bpn/transition.cpp new file mode 100644 index 0000000..77424be --- /dev/null +++ b/src/bpn/transition.cpp @@ -0,0 +1,358 @@ +//====================================================================================// +// // +// Transition classes inherit of node class // +// // +//====================================================================================// +// This File: transition.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 24/jan/20 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Transition class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Transition::Transition() +{ + //ctor +} + +//------------------------------------------------------------------------------ +// Named Constructor +//------------------------------------------------------------------------------ +Transition::Transition(simuleau_name _name):Node(_name) +{ + previousstate = state; + firingquantity = new FiringQuantity; +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Transition::~Transition() +{ + if (firingquantity) + delete firingquantity;//dtor +} + + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void Transition::Copy(const Transition *_transition) +{ + TransferNode(_transition); + firingquantity = new FiringQuantity; + firingquantity->Copy(_transition->firingquantity); +} + +//------------------------------------------------------------------------------ +// Set the previous state +//------------------------------------------------------------------------------ +void Transition::SetPreviousState(double _state) +{ + previousstate = _state; +} + + +//------------------------------------------------------------------------------ +// Compute states +//------------------------------------------------------------------------------ +void Transition::ComputeState() +{ + double transstate = 1.0; // enabled + double placestate; + Place *p; + + if (GetNumberOfInputArcs() == 0){ + state = 1.0; // enabled sink transition + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ +// p = simulation->sbpn->GetPlace(i); + p = inputnodes[i]; + placestate = p->GetState(); +// cout << "State of the place: " << placestate << endl; + transstate = min(transstate, placestate); + } + } + state = transstate; +// cout << "State of the transition: " << state << endl; + + } +} + +//========================Wodes20===========(modified version)==================================== +//------------------------------------------------------------------------------ +// Compute input place's marking quantity less than steady marking quantity states +//------------------------------------------------------------------------------ +int Transition::IsOnState() +{ + int transstate = 1; // enabled + Place *p; + double weight; + + if (GetNumberOfInputArcs() == 0){ + return 1; // enabled :source transition + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (inputarcs[i] != 0){ +// p = simulation->sbpn->GetPlace(i); + p = inputnodes[i]; + weight = -inputarcs[i]; + if (outputarcs[i] != 0 & inputarcs[i] != 0){ +// p = simulation->sbpn->GetPlace(i); + // for (int j=0; j<NumberOfTransitions(); j++) { + // V[j] = 0.0; + weight += outputarcs[i]; + } + + +// +// if (places[k]->GetWeightOfOutputArc(j) != 0.0 ){ +// V[j] = - places[k]->GetWeightOfOutputArc(j); +// // cout << " - V [" << j << "] " ; +// } +// if (places[k]->GetWeightOfInputArc(j) != 0.0 ){ +// // cout << " + V [" << j << "] " ; +// V[j] += places[k]->GetWeightOfInputArc(j); +// } +// +// +// if (outputarcs[i] != 0){ +//// p = simulation->sbpn->GetPlace(i); +// p = (Place*)outputnodes[i]; +// +// // for (int j=0; j<NumberOfTransitions(); j++) { +// // V[j] = 0.0; +// weight = outputarcs[i]; +// + switch (p->IsA()){ + case Continuous_pl : if (((ContinuousPlace*)p)->IsLessThanSteadyQuantity()& weight<0) + return 0; + break; + case Batch_pl : if (((BatchPlace*)p)->IsLessThanSteadyQuantity()& weight < 0) + return 0; + break; + } + } + } + } + return transstate; +} + +//=================================Vecos20============================================ + + +//------------------------------------------------------------------------------ +FiringQuantity* Transition::GetFiringQuantity() +{ + return (firingquantity); +} + +//------------------------------------------------------------------------------ +// Returns firing quantity +//------------------------------------------------------------------------------ + + +//==========================Steady firing quantity from initial marking============== +// +// It computes the steady firing quantity of each transition from initial marking. +//===================================================================================== +void Transition::SetSteadyFiringQuantity(double _firingquantity) +{ + firingquantity->SetSteadyFiringQuantity(_firingquantity); +} +//===================================================================================== +double Transition::GetSteadyFiringQuantity() +{ + return(steadyfiringquantity); +} + +//==========================Current firing quantity from initial marking============== +// +// It computes the current firing quantity of each transition from initial marking. +//===================================================================================== +//void Transition::setCurrentFiringQuantity(double _firingquantity) +//{ +// firingquantity->SetCurrentFiringQuantity(_firingquantity); +//} + +//====================================================================== + +double Transition::CurrentFiringQuantity(double steptime) +{ + Flow *f; + // FiringQuantity *firingquantity; + // Transition *t; + // double currentfiringquantity; + // currentfiringquantity=firingquantity->GetCurrentFiringQuantity(); + currentfiringquantity+= f->GetCurrentFlow() * steptime; + + // firingquantity=t->GetFiringQuantity(); + // firingquantity->SetCurrentFiringQuantity(currentfiringquantity); + return (currentfiringquantity); +} + + +//=========================================================================== +double Transition::GetCurrentFiringQuantity() +{ + return (currentfiringquantity); +} + + +//========================Vecos20======T_Z==================================== +//----------------------------------------------------------------------------------------------------------- +// Compute the set of T_Z that exist one output place satisfy Post(p_i, t_j)(z_j^s-z_j(m)) <= q_i^{f,s} +//----------------------------------------------------------------------------------------------------------- +int Transition::IsFiringQuantityOnState() +{ + double weight; + int transstate = 1; // enabled + Place *p; + // Transition *t; + // FiringQuantity *q; + double Zs; + double z; + + //q= t->GetFiringQuantity(); + Zs=firingquantity->GetSteadyFiringQuantity(); + z =firingquantity->GetCurrentFiringQuantity(); + + + if (GetNumberOfOutputArcs() == 0){ + return 1; // enabled sink transition + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ +// p = simulation->sbpn->GetPlace(i); + p = (Place*)outputnodes[i]; + + // for (int j=0; j<NumberOfTransitions(); j++) { + // V[j] = 0.0; + weight = outputarcs[i]; + switch (p->IsA()){ + case Continuous_pl : if (weight * (Zs-z) <= 0)// FreeSteadyMarkingQuantity= 0 in P^C + return 0; + break; + case Batch_pl : if (weight*(Zs-z) <= ((BatchPlace*)p)->GetFreeSteadyQuantity()) + return 0; + break; + } + } + } + } + return transstate; +} + + +//========================RBF========Event================================= +// It gets the rbf event. (a new ) objective : +//=========================================================================== +double Transition::GetRBFEvent() +{ + double date; + double min_date=-1.0; + double weight; + double transitionflow; + Flow *f; + Place *p; +// Transition *t; +// FiringQuantity *q; + double Zs; + double z; + + // q=t->GetFiringQuantity(); + Zs=firingquantity->GetSteadyFiringQuantity(); + z =firingquantity->GetCurrentFiringQuantity(); + + if (GetNumberOfOutputArcs() == 0){ + return (-1.0); + } + else if(z >= Zs){ + return (-1.0); + } + else{ + for (int i=0; i<numberofarcs; i++){ + if (outputarcs[i] != 0){ +// p = simulation->sbpn->GetPlace(i); + p = (Place*)outputnodes[i]; + + weight = outputarcs[i]; + // f=t->GetFlow(); + transitionflow=f->GetCurrentFlow(); + switch (p->IsA()){ + case Continuous_pl : + date = (Zs-z) / transitionflow; // FreeSteadyMarkingQuantity= 0 in P^C + date += simulation->stime->GetCurrentDate(); + + + break; + case Batch_pl : + date = (Zs-z -(((BatchPlace*)p)->GetFreeSteadyQuantity() / weight) / transitionflow); + if (date < 0){ + return (-1.0); + } + else{ + date += simulation->stime->GetCurrentDate(); + } + break; + } + if (date < min_date || min_date==-1.0){ + min_date= date; + } + } + } + return(min_date); + } + return (-1.0); +} +//----------------------------------------------------------------------------------- + + +//double BatchPlace::GetBOBEvent() +//{ +// double pos; +// double date; +// Batch b; +// +// if (marks->empty()){ +// return (-1.0); // no event of this type +// } +// +// if (state != 1.0){ +// b = marks->front(); +// pos = b.GetPosition(); +// date = (length - pos) / instantaneousspeed; +// date += simulation->stime->GetCurrentDate(); +// return (date); +// } +// return (-1.0); +//} + + + + + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Transition::Print(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Arcs: " << endl; + PrintArcs(fout); +} + diff --git a/src/bpn/transition.h b/src/bpn/transition.h new file mode 100644 index 0000000..b5cbceb --- /dev/null +++ b/src/bpn/transition.h @@ -0,0 +1,189 @@ +//====================================================================================// +// // +// Transition classes inherit of node class // +// // +//====================================================================================// +// This File: transition.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef TRANSITION_H +#define TRANSITION_H +#include <simuleau.h> +#include <flow.h> +#include <firingquantity.h> + + +//====================================================================================// +// Generic transition class // +//====================================================================================// +// Transition class implements a generic transition that will be used to implement // +// all other transition classes (discrete, continuous, batch) that can compose a // +// Batch Petri Net. // +//====================================================================================// +class Transition : public Node +{ + public: + Transition(); + Transition(simuleau_name _name); + virtual ~Transition(); + + + virtual void SetSteadyFiringQuantity(double _firingquantity); + FiringQuantity* GetFiringQuantity(); + + + void Copy(const Transition *_transition); + virtual trans_type IsA(){}; + + virtual Flow* GetFlow(){}; + virtual Flow* GetSteadyFlow(){}; + virtual int IsSteadyFlowReached(){}; + + void SetPreviousState(double _state); + virtual void ComputeState(); + int IsOnState(); + int IsFiringQuantityOnState(); // The current firing quantity satisfy belongs to T_z. +// double SteadyFiringQuantity(); // The steady firing quantity computed by the initial marking to a + // given steady state. (minimal firing quantity) + double GetSteadyFiringQuantity(); + double CurrentFiringQuantity(double steptime); // current firing quantity of transition. + double GetCurrentFiringQuantity(); //Get the current firing quantity + + double GetRBFEvent(); // + + + + virtual void WalkThrough(double duration){}; + // virtual void CurrentFiringQuantity(Simtime *_stime); + + // print functions + virtual void Print(ostream &fout); + + protected: + double previousstate; + FiringQuantity *firingquantity; + double steadyfiringquantity; + double currentfiringquantity; //Firing quantity from initial marking + private: +}; + + +//====================================================================================// +// Discrete transition class // +//====================================================================================// +// Discrete transition class associates a fire timing to discrete transitions. // +//====================================================================================// +class DiscreteTransition : public Transition +{ + public: + DiscreteTransition(); + DiscreteTransition(simuleau_name _name, double _time, double _steadytime); + virtual ~DiscreteTransition(); + + void Copy(const DiscreteTransition *_transition); + trans_type IsA(){return Discrete_tr;}; + + // simulation functions + void InitEnabledDate(); + void SetEnabledDate(double _date); + void ReserveMarksInputPlaces(); + + double GetTime(); + double GetSteadyTime(); + double GetEnabledDate(); + void ComputeState(); + double GetRBFEvent(); + + + void WalkThrough(double duration); + void FireDiscreteTransition(); + + + // print functions + void Print(ostream &fout); + + + protected: + double time; + double steadytime; + double enableddate; + private: +}; + +//====================================================================================// +// Continuous transition class // +//====================================================================================// +// Continuous transition class associates a flow to continuous transitions. // +//====================================================================================// +class ContinuousTransition : public Transition +{ + public: + ContinuousTransition(); + ContinuousTransition(simuleau_name _name, double _flow, double _steadyflow); + virtual ~ContinuousTransition(); + + void Copy(const ContinuousTransition *_transition); + virtual trans_type IsA(){return Continuous_tr;}; + + Flow* GetFlow(); + void SetInitialFlow(double _flow); + void SetTheoreticalFlow(double _flow); + int IsSteadyFlowReached(); + + double ComputeMinimumFlow(double f1, double f2); + virtual void ComputeTheoreticalFlow(); + + virtual void WalkThrough(double duration); + void FireContinuousTransition(double duration); + + double GetRBFEvent(); + + // print functions + void Print(ostream &fout); + virtual void Write(ostream &fout); + + protected: + Flow *flow; + + double ComputeTheoreticalFlowOfPlace(); + + private: +}; + + +//====================================================================================// +// Batch transition class // +//====================================================================================// +// Batch transition class associates a flow to batch transitions. // +//====================================================================================// +class BatchTransition : public ContinuousTransition +{ + public: + BatchTransition(); + BatchTransition(simuleau_name _name, double _flow, double _steadyflow); + virtual ~BatchTransition(); + + void Copy(const BatchTransition *_transition); + trans_type IsA(){return Batch_tr;}; + + double GetInputTheoreticalFlow(); + double GetOutputTheoreticalFlow(); + + void ComputeInputTheoreticalFlow(); + void ComputeOutputTheoreticalFlow(); + void ComputeTheoreticalFlow(); + double GetRBFEvent(); + // print functions + void Print(ostream &fout); + void Write(ostream &fout); + + protected: + double inputtheoreticalflow; + double outputtheoreticalflow; + private: +}; + +#endif // TRANSITION_H diff --git a/src/bpn/triangularbatchplace.cpp b/src/bpn/triangularbatchplace.cpp new file mode 100644 index 0000000..90f170a --- /dev/null +++ b/src/bpn/triangularbatchplace.cpp @@ -0,0 +1,1114 @@ +//====================================================================================// +// // +// Triangular batch place classes inherit of place class // +// // +//====================================================================================// +// This File: triangularbatchplace.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 22/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 22/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Triangular Batch Place class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +TriangularBatchPlace::TriangularBatchPlace() +{ + +} + +//------------------------------------------------------------------------------ +// Initialized Constructor +//------------------------------------------------------------------------------ +TriangularBatchPlace::TriangularBatchPlace(simuleau_name _name, double _speed, double _density, double _length, + double _flow):BatchPlace(_name, _speed, _density, _length) +{ + + flow = _flow; + maxflow = _flow; + marks = new list<ControllableBatch>; + marks->clear(); + initialmarks = new list<ControllableBatch>; + initialmarks->clear(); + steadymarks = new list<ControllableBatch>; + steadymarks->clear(); + +} +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +TriangularBatchPlace::~TriangularBatchPlace() +{ + if (marks) + delete[] marks; + if (initialmarks) + delete[] initialmarks; + if (steadymarks) + delete[] steadymarks; + +} + + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void TriangularBatchPlace::Copy(const TriangularBatchPlace * _place) +{ + TransferNode(_place); + + conflict = _place->conflict; + structuralconflict = _place->structuralconflict; + + // batch place + behaviour = _place->behaviour; + formalisation = _place->formalisation; + + density = _place->density; + maxspeed = _place->maxspeed; + speed = _place->speed; + instantaneousspeed = _place->instantaneousspeed; + length = _place->length; + flow = _place->flow; + maxflow = _place->maxflow; + + marks = new list<ControllableBatch>; + marks->clear(); + + for (list<ControllableBatch>::iterator it=_place->marks->begin(); it!=_place->marks->end(); ++it) { + ControllableBatch *newbatch = new ControllableBatch; + newbatch->Copy(*it); + marks->push_back(*newbatch); + } + + initialmarks = new list<ControllableBatch>; + initialmarks->clear(); + + for (list<ControllableBatch>::iterator it=_place->initialmarks->begin(); it!=_place->initialmarks->end(); ++it) { + ControllableBatch *newbatch = new ControllableBatch; + newbatch->Copy(*it); + initialmarks->push_back(*newbatch); + } + + + steadymarks = new list<ControllableBatch>; + steadymarks->clear(); + + for (list<ControllableBatch>::iterator it=_place->steadymarks->begin(); it!=_place->steadymarks->end(); ++it) { + ControllableBatch *newbatch = new ControllableBatch; + newbatch->Copy(*it); + steadymarks->push_back(*newbatch); + } + + } + +//------------------------------------------------------------------------------ +// It set the initial marking of the place +//------------------------------------------------------------------------------ +void TriangularBatchPlace::AddBatchToInitialMarking(ControllableBatch &b) +{ + initialmarks->push_back(b); + marks->push_back(b); +} + +//------------------------------------------------------------------------------ +// It add a batch to the steady marking of the place +//------------------------------------------------------------------------------ +void TriangularBatchPlace::AddBatchToSteadyMarking(ControllableBatch &b) +{ + steadymarks->push_back(b); +} + +//------------------------------------------------------------------------------ +// It add a batch to the marking of the place +//------------------------------------------------------------------------------ +void TriangularBatchPlace::AddBatchToMarking(ControllableBatch &b) +{ + marks->push_back(b); +} + + +//------------------------------------------------------------------------------ +// It set the new flow +//------------------------------------------------------------------------------ +void TriangularBatchPlace::SetFlow(double _flow) +{ + flow = _flow; +} + +//------------------------------------------------------------------------------ +// It set the maximum flow +//------------------------------------------------------------------------------ +void TriangularBatchPlace::SetMaxFlow(double _flow) +{ + maxflow = _flow; +} + +//------------------------------------------------------------------------------ +// It set the new flow +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetFlow() +{ + return (flow); +} + +//------------------------------------------------------------------------------ +// It set the maximum flow +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetMaxFlow() +{ + return (maxflow); +} + +//------------------------------------------------------------------------------ +// It returns true if the triangular batch place is full +//------------------------------------------------------------------------------ +int TriangularBatchPlace::IsFull() +{ + double full = length * density; + double quantity = 0.0; + + if (marks->size() != 0){ + for (list<ControllableBatch>::iterator cb=marks->begin(); cb!=marks->end(); cb++) { + quantity += cb->GetDensity() * cb->GetLength(); + } + if (abs(quantity - full) < PRF::prf.Min_Err()){ + return 1; + } + else{ + return 0; + } + } + else { + return 0; + } +} + + +//------------------------------------------------------------------------------ +// It returns true if the place has an output batch +//------------------------------------------------------------------------------ +int TriangularBatchPlace::HasOutputBatch() +{ + int result; + + ControllableBatch cb; + + if (marks->size() == 0){ + result = 0; + } + else{ + cb = marks->front(); + if ((length - cb.GetPosition()) <= PRF::prf.Min_Err()){ + result = 1; + } + else{ + result = 0; + } + } + return (result); +} + + +//------------------------------------------------------------------------------ +// It returns the output controllable batch +//------------------------------------------------------------------------------ +ControllableBatch* TriangularBatchPlace::GetOutputControllableBatch() +{ + if (HasOutputBatch()){ + return (&marks->front()); + } + else{ + return (NULL); + } +} + +//------------------------------------------------------------------------------ +// It returns the critical density +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetCriticalDensity() +{ + double dcri; + dcri = ((GetPropagationSpeed() * density) / (instantaneousspeed + GetPropagationSpeed())); + return (dcri); +} + +//------------------------------------------------------------------------------ +// It returns the density of the output batch +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetDensityOutputBatch() +{ + double densityoutputbatch = 0.0; + ControllableBatch *cb; + + if (HasOutputBatch()){ + cb = GetOutputControllableBatch(); + densityoutputbatch = cb->GetDensity(); + } + return (densityoutputbatch); +} + +//------------------------------------------------------------------------------ +// It returns the speed of the output batch +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetSpeedOutputBatch() +{ + double speedoutputbatch = 0.0; + ControllableBatch *cb; + + if (HasOutputBatch()){ + cb = GetOutputControllableBatch(); + speedoutputbatch = cb->GetSpeed(); + } + return (speedoutputbatch); +} + +//------------------------------------------------------------------------------ +// It returns the flow of the output batch +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetFlowOutputBatch() +{ + return (GetDensityOutputBatch() * GetSpeedOutputBatch()); +} + +//------------------------------------------------------------------------------ +// It returns the congested density of the place +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetCongestionDensity() +{ + return (density - (GetOutputTransitonsFlow() / GetPropagationSpeed())); +} + +//------------------------------------------------------------------------------ +// It returns the propagation speed of congestion/decongestion +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetPropagationSpeed() +{ + double w; + w = (maxflow * maxspeed) / (density * maxspeed - maxflow); + return (w); +} + + +//------------------------------------------------------------------------------ +// It computes the state of the triangular batch place +//------------------------------------------------------------------------------ +void TriangularBatchPlace::ComputeState() +{ + if (marks->empty()){ + state = 0.0; + } + else{ + if (HasOutputBatch() == 1){ + state = 1.0; + } + else{ + state = 0.0; + } + } +} + + +//------------------------------------------------------------------------------ +// It creates a controllable batch if the place has a least an input transition (continuous or batch) +// and the input flow is non-null +// It returns a positive value if a batch was created and 0 otherwise +// TODO verify multiple input transitions +//------------------------------------------------------------------------------ +int TriangularBatchPlace::CreateBatches() +{ + double inputtransflow = 0.0; + int result = 0; + + Transition *t; + Flow *f; + ControllableBatch *newcb; + + formalisation = no; + + if (GetNumberOfInputArcs() != 0){ + inputtransflow = GetInputTransitonsFlow(); + if (inputtransflow > 0.0){ + if (!marks->empty()){ + ControllableBatch &cb = marks->back(); + if ((cb.GetLength() != 0.0 ) && (cb.GetPosition() != 0.0)){ + newcb = new ControllableBatch(inputtransflow, instantaneousspeed); + AddBatchToMarking(*newcb); + } + } + else{ + newcb = new ControllableBatch(inputtransflow, instantaneousspeed); + AddBatchToMarking(*newcb); + } + } + } +} + +//------------------------------------------------------------------------------ +// It merges the batch that have the same speed and density and are in contact +//------------------------------------------------------------------------------ +void TriangularBatchPlace::MergeBatches() +{ + int merged = 0; + double endposition; + double newlength; + int numberofbatches = marks->size(); + ControllableBatch *newcb; + list<ControllableBatch> *newmarks = new list<ControllableBatch>; + list<ControllableBatch>::iterator cb1, cb2, cbi; + + if (numberofbatches > 1){ + cb1 = marks->begin(); + cbi = marks->begin(); + cbi++; + for (int i=1; i<numberofbatches; i++){ + endposition = cb1->GetPosition() - cb1->GetLength(); + cb2 = cbi; + + if ((abs(cb1->GetDensity() - cb2->GetDensity()) < PRF::prf.Min_Err()) && + (abs(cb2->GetPosition() - endposition) < PRF::prf.Min_Err())){ // merge batches + newlength = cb1->GetLength() + cb2->GetLength(); + cb1->SetLength(newlength); + cbi++; + merged = 1; + } + else{ + newcb = new ControllableBatch; + newcb->Copy(*cb1); + newmarks->push_back(*newcb); + cb1 = cb2; + cbi++; + merged = 0; + } + } + + newcb = new ControllableBatch; + if (merged){ + newcb->Copy(*cb1); + } + else{ + newcb->Copy(*cb2); + } + + newmarks->push_back(*newcb); + marks->clear(); + marks = newmarks; + } +} + +//------------------------------------------------------------------------------ +// It destructs the Controllable batches that have a length or density equal to 0 +// and are not the input batch (position equal to length) +//------------------------------------------------------------------------------ +void TriangularBatchPlace::DestructBatches() +{ + int numberofbatches = marks->size(); + ControllableBatch *newcb; + list<ControllableBatch> *newmarks = new list<ControllableBatch>; + list<ControllableBatch>::iterator cb1; + + if (numberofbatches != 0){ + for (cb1=marks->begin(); cb1!=marks->end(); ++cb1) { + if ((cb1->GetLength() > PRF::prf.Min_Err()) || ((cb1->GetPosition() == 0.0) && (cb1->GetLength() == 0.0))){ + newcb = new ControllableBatch; + newcb->Copy(*cb1); + newmarks->push_back(*newcb); + } + } + marks->clear(); + marks = newmarks; + } +} + +//------------------------------------------------------------------------------ +// It computes the behaviour of a triangular batch place +// TODO all batch places have no structural conflit +//------------------------------------------------------------------------------ +void TriangularBatchPlace::ComputeBehaviour() +{ + int i=0; + double outflow; + double trflow; + double pcb_speed = -1.0; + list<ControllableBatch>::iterator cbi, pcbi; + ControllableBatch *cb, *pcb; + ControllableBatch *ocb = NULL; + + if (HasOutputBatch()){ + ocb = GetOutputControllableBatch(); + } + + for (i=0, cbi=marks->begin(); cbi!=marks->end(); ++i, ++cbi) { + cb = (ControllableBatch*) &(*cbi); + if (cb == ocb){ + outflow = ocb->GetFlow(); + trflow = GetOutputTransitonsFlow(); + + if (cb->GetState(this) == Free_st){ + if ((outflow - trflow) <= PRF::prf.Min_Err()){ + cb->SetBehaviour(Free_behaviour); + } + else{ + cb->SetBehaviour(Congesting_behaviour); + } + } + else{ // not free state + if ((outflow - trflow) < (-PRF::prf.Min_Err())){ + cb->SetBehaviour(Uncongesting_behaviour); + } + else{ + if ((outflow - trflow) > PRF::prf.Min_Err()){ + cb->SetBehaviour(Congesting_behaviour); + } + else{ + cb->SetBehaviour(Free_behaviour); + } + } + } + } + else{ // not the output batch + pcbi = cbi; + pcbi--; // previous controllable batch iterator; + pcb = (ControllableBatch*) &(*pcbi); // previous controllable batch + pcb_speed = -1.0; + + if ((i!=0) && (cb != pcb) && (cb->IsInContactWithByFront(*pcb))){ + pcb_speed = pcb->GetSpeed(); + } + + if (cb->GetState(this) == Free_st){ + if ((pcb_speed >= 0.0) && (pcb_speed < cb->GetSpeed())){ + cb->SetBehaviour(Congesting_behaviour); + } + else{ + cb->SetBehaviour(Free_behaviour); + } + } + else{ + if ((pcb_speed >= 0.0) && (pcb_speed < cb->GetSpeed())){ // <= + cb->SetBehaviour(Congesting_behaviour); + } + else{ + cb->SetBehaviour(Uncongesting_behaviour); + } + } + } + } +} + + +//------------------------------------------------------------------------------ +// This function sets the new speed and recompute the state of the controllable batches +//------------------------------------------------------------------------------ +void TriangularBatchPlace::SetAndRecomputeSpeed(double newspeed) +{ + ctrl_batch_state st; + double newcriticaldensity; + + for (list<ControllableBatch>::iterator cbi=marks->begin(); cbi!=marks->end(); ++cbi) { + st = cbi->GetState(this); + if (newspeed < instantaneousspeed){ + if ((st == Free_st) || (st == Congested_st) && (cbi->GetSpeed() > newspeed)){ + cbi->SetSpeed(newspeed); + } + } + else{ + if (newspeed > instantaneousspeed){ + newcriticaldensity = flow / newspeed; + if (st == Free_st) { + if (cbi->GetDensity() <= newcriticaldensity){ + cbi->SetSpeed(newspeed); + } + else{ + cbi->SetSpeed(GetPropagationSpeed() * (density - cbi->GetDensity()) / cbi->GetDensity()); + } + } + } + } + } + SetSpeed(newspeed); +} + + + +//------------------------------------------------------------------------------ +// This function sets the corresponding evolution function to each batch +//------------------------------------------------------------------------------ +void TriangularBatchPlace::SetBehaviourFunctions() +{ + int i=0; + list<ControllableBatch>::iterator cbi; + + for (i=0, cbi=marks->begin(); cbi!=marks->end(); ++i, ++cbi) { + switch(cbi->GetBehaviour()){ + case Free_behaviour: SetFunctionFreeBatch(cbi, i); + break; + case Congesting_behaviour: SetFunctionCongestedBatch(cbi, i); + break; + case Uncongesting_behaviour: SetFunctionUncongestingBatch(cbi, i); + break; + } + } +} + +//------------------------------------------------------------------------------ +// It sets the evolution function to a free batch +//------------------------------------------------------------------------------ +void TriangularBatchPlace::SetFunctionFreeBatch(list<ControllableBatch>::iterator cbi, int i) +{ + switch(cbi->GetState(this)){ + case Free_st : cbi->SetEvolveFunction(&ControllableBatch::EvolveInFreeBehaviour); + break; + case Congested_st : cbi->SetEvolveFunction(&ControllableBatch::EvolveInCongestingOutputBehaviour); + break; + } +} + + +//------------------------------------------------------------------------------ +// It sets the evolution function to a congested batch +// TODO verify cbi adn pcbi +//------------------------------------------------------------------------------ +void TriangularBatchPlace::SetFunctionCongestedBatch(list<ControllableBatch>::iterator cbi, int i) +{ + double diffdensity; + + list<ControllableBatch>::iterator pcbi = prev(cbi); + list<ControllableBatch>::iterator ncbi = next(cbi); + + int cbiisoutputbatch = cbi->IsOutputControllableBatch(this); + int pcbiisoutputbatch = pcbi->IsOutputControllableBatch(this); + + cbi->SetEvolveFunction(&ControllableBatch::EvolveInFreeBehaviour); // default case + + if (cbiisoutputbatch) { + diffdensity = cbi->GetDensity() - GetCongestionDensity(); + if (abs(diffdensity) <= PRF::prf.Min_Err()){ + if (cbi->GetBehaviour() == Congesting_behaviour){ + cbi->SetEvolveFunction(&ControllableBatch::EvolveInCongestingOutputBehaviour); + } + } + else{ // density != congestion density and cbi is outpubatch + ControllableBatch *newcb = new ControllableBatch; + newcb->Copy(*cbi); // create a copy of the current batch + + newcb->SetLength(0.0); + newcb->SetDensity(GetCongestionDensity()); + newcb->SetSpeed(GetFlowOfOutputTransition() / GetCongestionDensity()); + newcb->SetEvolveFunction(&ControllableBatch::EvolveInFreeToCongestingBehaviourCongBatch); + + marks->insert(cbi, *newcb); + + // set function cbi + cbi->SetEvolveFunction(&ControllableBatch::EvolveInFreeToCongestingBehaviourFreeBatch); + cbi++; + } + } + else{ + if ((!cbiisoutputbatch) && (i != 0) && (cbi->IsInContactWithByFront(*pcbi))){ + ControllableBatch *newcb = new ControllableBatch; + newcb->Copy(*cbi); // create a copy of the current batch + + + newcb->SetLength(0.0); + newcb->SetDensity(pcbi->GetDensity()); + newcb->SetSpeed(pcbi->GetSpeed()); + newcb->SetEvolveFunction(&ControllableBatch::EvolveInFreeToCongestingBehaviourMiddlePlaceWithContactCongBatch); + + marks->insert(cbi, *newcb); + // set function + cbi->SetEvolveFunction(&ControllableBatch::EvolveInFreeToCongestingBehaviourMiddlePlaceWithContactFreeBatch); + cbi++; + } + } +} + + +//------------------------------------------------------------------------------ +// It sets the evolution function to an uncongesting batch +//------------------------------------------------------------------------------ +void TriangularBatchPlace::SetFunctionUncongestingBatch(list<ControllableBatch>::iterator cbi, int i) +{ + double diffdensity; + double downflow; + + list<ControllableBatch>::iterator pcbi = prev(cbi); + list<ControllableBatch>::iterator ncbi = next(cbi); + + int cbiisoutputbatch = cbi->IsOutputControllableBatch(this); + int pcbiisoutputbatch = pcbi->IsOutputControllableBatch(this); + + cbi->SetEvolveFunction(&ControllableBatch::EvolveInFreeBehaviour); // default case + + if (cbiisoutputbatch){ + downflow = GetOutputTransitonsFlow(); + diffdensity = pcbi->GetDensity() - (downflow/instantaneousspeed); + if (abs(diffdensity) <= PRF::prf.Min_Err()){ + if (cbi->GetBehaviour() == Uncongesting_behaviour){ + cbi->SetEvolveFunction(&ControllableBatch::EvolveInUncongestingOutputBehaviour); + } + } + else{ + ControllableBatch *newcb = new ControllableBatch; + newcb->Copy(*cbi); + + newcb->SetLength(0.0); + newcb->SetDensity(downflow/instantaneousspeed); + newcb->SetSpeed(instantaneousspeed); + newcb->SetEvolveFunction(&ControllableBatch::EvolveInFreeToCongestingBehaviourCongBatch); + marks->insert(cbi, *newcb); // create a copy of the current batch + + //update batches evolve functions + cbi->SetEvolveFunction(&ControllableBatch::EvolveInFreeToCongestingBehaviourFreeBatch); + cbi++; + } + } + else{ + if (!cbiisoutputbatch && (i == 0)){ + // create a new batch + ControllableBatch *newcb = new ControllableBatch; + newcb->Copy(*cbi); + + newcb->SetLength(0.0); + newcb->SetDensity(GetCriticalDensity()); + newcb->SetSpeed(instantaneousspeed); + newcb->SetEvolveFunction(&ControllableBatch::EvolveInUncongestingToFreeBehaviourFreeBatch); + marks->insert(cbi, *newcb); // create a copy of the current batch + + //update batches evolve functions + cbi->SetEvolveFunction(&ControllableBatch::EvolveInUncongestingToFreeBehaviourCongBatch); + cbi++; + } + else{ + if (!cbiisoutputbatch && (i != 0) && cbi->IsInContactWithByFront(*pcbi)){ + ControllableBatch *newcb = new ControllableBatch; + newcb->Copy(*cbi); + if ((pcbi->GetState(this) == Congested_st) && pcbi->GetSpeed() > cbi->GetSpeed()){ + newcb->SetLength(0.0); + newcb->SetDensity(pcbi->GetDensity()); + newcb->SetSpeed(pcbi->GetSpeed()); + //update batches evolve functions + newcb->SetEvolveFunction(&ControllableBatch::EvolveInFreeToCongestingBehaviourMiddlePlaceWithContactCongBatch); + marks->insert(cbi, *newcb); // create a copy of the current batch + cbi->SetEvolveFunction(&ControllableBatch::EvolveInFreeToCongestingBehaviourMiddlePlaceWithContactFreeBatch); + } + else{ + newcb->SetLength(0.0); + newcb->SetDensity(GetCriticalDensity()); + newcb->SetSpeed(instantaneousspeed); + //update batches evolve functions + newcb->SetEvolveFunction(&ControllableBatch::EvolveInUncongestingToFreeBehaviourFreeBatch); + cbi->SetEvolveFunction(&ControllableBatch::EvolveInUncongestingToFreeBehaviourCongBatch); + marks->insert(cbi, *newcb); // create a copy of the current batch + } + cbi++; + } + } + } +} + +//------------------------------------------------------------------------------ +// It evolves the marks (controllable batches) of the triangular batch place +//------------------------------------------------------------------------------ +void TriangularBatchPlace::EvolveMarks(double _date) +{ +/* cout << "========================\n" << "Before evolution\n" << "========================\n"; + for (list<ControllableBatch>::iterator cbi=marks->begin(); cbi!=marks->end(); ++cbi) { + cbi->Print(ofstream &fout); + } +*/ + for (list<ControllableBatch>::iterator cbi=marks->begin(); cbi!=marks->end(); ++cbi) { + EvolveControllableBatch(cbi, _date); + // fixerror? + } +/* cout << "========================\n" << "After evolution\n" << "========================\n"; + for (list<ControllableBatch>::iterator cbi=marks->begin(); cbi!=marks->end(); ++cbi) { + cbi->Print(ofstream &fout); + } +*/ +} + +//------------------------------------------------------------------------------ +// It evolves a specific controllable batch +// TODO: verify first and last batch +//------------------------------------------------------------------------------ +void TriangularBatchPlace::EvolveControllableBatch(list<ControllableBatch>::iterator cbi, double _date) +{ + list<ControllableBatch>::iterator pcbi = cbi; + list<ControllableBatch>::iterator ncbi = cbi; + ControllableBatch *cb, *pcb, *ncb; + + pcbi--; + ncbi++; + + cb = (ControllableBatch*) &(*cbi); + pcb = (ControllableBatch*) &(*pcbi); + ncb = (ControllableBatch*) &(*ncbi); + + cb->Evolve(simulation->stime, this, pcb, ncb); +} + +//------------------------------------------------------------------------------ +// It computes the date of the next event to a Controllable Batch becomes an Output Batch type +// returns -1.0 if no BOB event is possible +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetBOBEvent() +{ + double cbpos; + double cbspeed; + double date; + ControllableBatch cb; + + if (marks->empty()){ + return (-1.0); // no event of this type + } + + if (state != 1.0){ + cb = marks->front(); + cbpos = cb.GetPosition(); + cbspeed = cb.GetSpeed(); + date = (length - cbpos) / cbspeed; + date += simulation->stime->GetCurrentDate(); + return (date); + } + return (-1.0); +} + + +//------------------------------------------------------------------------------ +// It computes the date of the next event to a Destruction of an Output Batch type +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetDOBEvent() +{ + double date = -1.0; + double outputflow = GetOutputTransitonsFlow(); + ControllableBatch *ocb; + + if (HasOutputBatch() == 1){ + ocb = GetOutputControllableBatch(); + if (ocb->GetState(this) == Free_st){ // free state + if ((ocb->GetBehaviour() == Free_behaviour) && (instantaneousspeed != 0.0)){ + date = simulation->stime->GetCurrentDate() + (ocb->GetLength()/ocb->GetSpeed()); + } + } + else{ + if((outputflow != 0.0) && ((ocb->GetBehaviour() == Free_behaviour))) { +// date = simulation->stime->GetCurrentDate() + cb->GetLength() * GetCongestionDensity() / outputflow; + date = ocb->GetLength() * ocb->GetDensity() / outputflow; + date += simulation->stime->GetCurrentDate(); + } + } + } + return (date); +} + +//------------------------------------------------------------------------------ +// It computes the date of the next event to a Full accumulation/congestion of any batch +// (Batch Becomes Dense) type +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetBBDEvent() +{ + double date = -1.0; + double mindate = -1.0; + int i = 0; + double diffdensity; // difference of densities + double outputtransitionflow; + double congesteddensity; + ControllableBatch *ocb; + list<ControllableBatch>::iterator pcb; // previous controllable batch + + i = 0; + for (list<ControllableBatch>::iterator cb=marks->begin(); cb!=marks->end(); ++cb, i++) { + if (cb->IsOutputControllableBatch(this)) { // congestion of the output batch + congesteddensity = GetCongestionDensity(); + if ((cb->GetBehaviour() == Congesting_behaviour) && (abs(congesteddensity - cb->GetDensity()) > PRF::prf.Min_Err())){ + outputtransitionflow = GetOutputTransitonsFlow(); + date = cb->GetLength() * (congesteddensity - cb->GetDensity()) / (cb->GetSpeed() * congesteddensity - outputtransitionflow); + date = date + simulation->stime->GetCurrentDate(); + } + } + else{ + if (i != 0){ + pcb = cb; + pcb--; + + diffdensity = pcb->GetDensity() - cb->GetDensity(); + + if (cb->IsInContactWithByFront(*pcb) && (diffdensity > PRF::prf.Min_Err())){ // in contact, compute date to full congestion + date = (cb->GetLength() * diffdensity) / ((cb->GetSpeed() * pcb->GetDensity()) - (pcb->GetSpeed() * pcb->GetDensity())) ; + date = date + simulation->stime->GetCurrentDate(); + } + } + } + // get the minimal date + if ((mindate > date) || (mindate == -1.0)) { + mindate = date; + } + } + + return (mindate); +} + +//------------------------------------------------------------------------------ +// It computes the date of the next event to a Two Batches Meet +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetTBMEvent() +{ + + double date = -1.0; + double mindate = -1.0; + int i = 0; + double diffdensity; // difference of densities + list<ControllableBatch>::iterator pcb; // previous controllable batch + + if (marks->size() <= 1) + return(date); + + i = 0; + for (list<ControllableBatch>::iterator cb=marks->begin(); cb!=marks->end(); ++cb, i++) { + if (cb->IsOutputControllableBatch(this) || i==0 ) // not previous lot + continue; + + pcb = cb; + pcb--; + + if (pcb->GetState() == Free_st) // Front batch is a free batch + continue; + + if ((pcb->GetState() == Congested_st) && (pcb->IsOutputControllableBatch(this))) + continue; // bmob event + + diffdensity = pcb->GetDensity() - cb->GetDensity(); + + + if (((cb->GetSpeed() - pcb->GetSpeed()) > PRF::prf.Min_Err()) && (diffdensity > PRF::prf.Min_Err())) { // compute meeting date + date = simulation->stime->GetCurrentDate() + + (cb->GetPosition() - pcb->GetPosition() + pcb->GetLength()) / (pcb->GetSpeed() - cb->GetSpeed()) ; + } + + // get the minimal date + if ((mindate > date) || (mindate == -1.0)) { + mindate = date; + } + } + + return (mindate); +} + +//------------------------------------------------------------------------------ +// It computes the date of the next event to a Batch Meets Output Batch +// TODO: review this method +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetBMOBEvent() +{ + double date = -1.0; + double outputtransitionflow; + double congesteddensity; + ControllableBatch *ocb; + list<ControllableBatch>::iterator cb; + + +/* if ((HasOutputBatch() == 0) || (marks->size() <= 1)){ + return (date); + } + + ocb = GetOutputControllableBatch(); + cb = marks->begin(); + cb++; + congesteddensity = GetCongestionDensity(); + + if (//(abs(congesteddensity - ocb->GetDensity()) < PRF::prf.Min_Err()) && + (ocb->GetState() == Congested_st)){ // output batch is congested + outputtransitionflow = GetOutputTransitonsFlow(); + if ((cb->GetBehaviour() != Congesting_behaviour) && (!cb->IsInContactWithByFront(*ocb))){ // batches are not in contact + if (((congesteddensity * cb->GetSpeed()) - outputtransitionflow) != 0){ // maybe congesteddensity is ocb->density + date = simulation->stime->GetCurrentDate() + + (congesteddensity * (length - ocb->GetLength() - cb->GetPosition()) / ( (cb->GetSpeed() * congesteddensity) - outputtransitionflow)); + } + } + else{ + if (((congesteddensity - cb->GetDensity()) > PRF::prf.Min_Err()) && (cb->GetLength() > PRF::prf.Min_Err()) && + (cb->GetSpeed() > PRF::prf.Min_Err()) && (abs(congesteddensity - cb->GetDensity()) > PRF::prf.Min_Err())){ + date = simulation->stime->GetCurrentDate() + + (((congesteddensity - cb->GetDensity()) * cb->GetLength()) / ((cb->GetSpeed() * congesteddensity) - outputtransitionflow)); + } + } + } +*/ + return (date); + +} + +//------------------------------------------------------------------------------ +// It computes the date of the next event to Output Batch Decongestion +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetOBDEvent() +{ + double date = -1; + double outflow; + double ddensity; + ControllableBatch *ocb; + + if (HasOutputBatch() == 0) + return (date); + + outflow = GetOutputTransitonsFlow(); + ddensity = outflow / GetInstantaneousSpeed(); + ocb = GetOutputControllableBatch(); + + if ((ocb->GetBehaviour() == Uncongesting_behaviour) && (abs(ocb->GetDensity() - ddensity) > PRF::prf.Min_Err())){ + if (abs(ocb->GetSpeed() * ddensity - outflow) > PRF::prf.Min_Err()){ + date = ( simulation->stime->GetCurrentDate() + + (ocb->GetLength() * (ddensity - ocb->GetDensity())) / ((ocb->GetSpeed() * ddensity) - outflow)); + } + } + return (date); +} + +//------------------------------------------------------------------------------ +// It computes the date of the next event to Batch Decongestion +// TODO : review this method for all batches +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetBDEvent() +{ + int i = 0; + double date = -1; + double mindate = -1; + double diffdensity; // difference of densities + list<ControllableBatch>::iterator pcb; // previous controllable batch + + if (marks->size() <= 1) + return(date); + + i = 0; + for (list<ControllableBatch>::iterator cb=marks->begin(); cb!=marks->end(); ++cb, i++) { + if (i == 0) // BBF event + continue; + + if (cb->IsOutputControllableBatch(this)) + continue; // OBD event + + if (cb->GetBehaviour() != Uncongesting_behaviour) + continue; + + pcb = cb; + pcb--; + + if (!cb->IsInContactWithByFront(*pcb)) // BFF event + continue; + + diffdensity = pcb->GetDensity() - cb->GetDensity(); + if (((cb->GetSpeed() - pcb->GetSpeed()) < PRF::prf.Min_Err()) && (diffdensity < PRF::prf.Min_Err())) { // verify if need diffdensity + date = (cb->GetLength() * diffdensity) / ((cb->GetSpeed() * pcb->GetDensity()) - (pcb->GetSpeed() * pcb->GetDensity())); + date = date + simulation->stime->GetCurrentDate(); + } + + // get the minimal date + if ((mindate > date) || (mindate == -1.0)) { + mindate = date; + } + } + return (date); +} + +//------------------------------------------------------------------------------ +// It computes the date of the next event to Batch Becomes Free +//------------------------------------------------------------------------------ +double TriangularBatchPlace::GetBBFEvent() +{ + double date = -1; + double mindate = -1; + int i = 0; + list<ControllableBatch>::iterator pcb; // previous controllable batch + + i = 0; + for (list<ControllableBatch>::iterator cb=marks->begin(); cb!=marks->end(); ++cb, i++) { + if (cb->IsOutputControllableBatch(this)) + continue; + if (cb->GetBehaviour() != Uncongesting_behaviour) + continue; + + pcb = cb; + pcb--; + + if ((i == 0) || (!cb->IsInContactWithByFront(*pcb))){ + date = (cb->GetLength() * (GetCriticalDensity() - cb->GetDensity())) / ((cb->GetSpeed() * GetCriticalDensity()) - (instantaneousspeed * GetCriticalDensity())); + date = date + simulation->stime->GetCurrentDate(); + + } + + // get the minimal date + if ((mindate > date) || (mindate == -1.0)) { + mindate = date; + } + } + return (date); +} + + + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void TriangularBatchPlace::Print(ostream &fout) +{ fout << "Name: " << name << endl; + fout << " Type: " << "Triangular Batch" << endl; + fout << " Behaviour: " << behaviour << endl; + fout << " Density: " << density << endl; + fout << " Maximum speed: " << maxspeed << endl; + fout << " Speed: " << speed << endl; + fout << " Length: " << length << endl; + fout << " Maximum Flow: " << maxflow << endl; + fout << " Flow: " << flow << endl; + fout << " Initial Tr. Batches:" << initialmarks->size() << endl; + + for (list<ControllableBatch>::iterator it=initialmarks->begin(); it!=initialmarks->end(); ++it) { + it->GetState(this); + it->Print(fout); + } + + if (!steadymarks->empty()){ + fout << " Steady Tr. Batches: " << steadymarks->size() << endl; + + for (list<ControllableBatch>::iterator it=steadymarks->begin(); it!=steadymarks->end(); ++it) { + it->GetState(this); + it->Print(fout); + } + } + + fout << " Triangular Batches: " << marks->size() << endl; + + for (list<ControllableBatch>::iterator it=marks->begin(); it!=marks->end(); ++it) { + it->GetState(this); + it->Print(fout); + } + fout << " Arcs: " << endl; + PrintArcs(fout); +} + + +//------------------------------------------------------------------------------ +// Write +//------------------------------------------------------------------------------ +void TriangularBatchPlace::Write(ostream &fout) +{ + fout << "Name: " << name << endl; + fout << " Type: " << "Triangular Batch" << endl; + fout << " Density: " << density << endl; + fout << " Speed: " << speed << endl; + fout << " Length: " << length << endl; + fout << " Flow: " << flow << endl; + fout << " Batches: " << marks->size() << endl; + + for (list<ControllableBatch>::iterator it=marks->begin(); it!=marks->end(); ++it) { + it->GetState(this); + it->Write(fout); + } +} diff --git a/src/interf/bpnfile.h b/src/interf/bpnfile.h new file mode 100644 index 0000000..6f8ec24 --- /dev/null +++ b/src/interf/bpnfile.h @@ -0,0 +1,5 @@ +#include "simuleau.h" +#include "y.tab.h" +#include "error_msgs.h" + +using namespace std; diff --git a/src/interf/error_msgs.h b/src/interf/error_msgs.h new file mode 100644 index 0000000..1cfceb4 --- /dev/null +++ b/src/interf/error_msgs.h @@ -0,0 +1,92 @@ +//====================================================================================// +// // +// Error Messages // +// // +//====================================================================================// +// This File: error_msgs.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 12/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 12/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +// This file has macro definitions to put error messages of SIMULEAU parser // +//====================================================================================// +#ifndef _ERROR_MSGS_H_ +#define _ERROR_MSGS_H_ + +#define Lexical_Error(yacc_number, yacc_line, id) \ + cout << " " << yacc_number \ + << ":Line(" << yacc_line \ + << ") - Lexical Error - \"" << id \ + << "\" is an unrecognized symbol." \ + << endl; + +#define Syntatic_Error(yacc_number, yacc_line, str, id) \ + cout << " " << yacc_number \ + << ":Line(" << yacc_line \ + << ") - " << str << " - \"" << id \ + << "\" (not expected)." \ + << endl; + +#define Semantic_Error_YACC(yacc_number, yacc_line, id, number) \ + cout << " " << yacc_number \ + << ":Line(" << yacc_line \ + << ") - Semantic Error - " << id \ + << " - (" << number << ")." \ + << endl; + +#define Semantic_Error(text, number) \ + cout << "Semantic Error - " << number << " (** " \ + << text << " **).\n"; + +#define Semantic_Warning(text_1, text_2, number) \ + cout << "Semantic Warning - " << number << " (** " \ + << text_1 << " - " << text_2 << " **)." \ + << endl; + +#define Programming_Error1(text) \ + cout << "Programming Error - at \"" << text \ + << "\" (file '" << __FILE__ << "' - line " << __LINE__ << ")" \ + << endl; + +#define Programming_Error2(text, number) \ + cout << "Programming Error - " << number << " (at " \ + << text << ")\n" \ + << "(file '" << __FILE__ << "' - line " << __LINE__ << ")" \ + << endl; + +// Semantic Errors - YACC (00 .. 99) +#define Parser_00 "Place name already defined in this model" +#define Parser_01 "Transition name already defined in this model" +#define Parser_02 "can not solve identifier." +#define Parser_03 "automaton identifier already defined." +#define Parser_04 "event not declared." +#define Parser_05 "state identifier already defined for this automaton." +#define Parser_06 "state identifier already defined as function identifier." + +// Semantic Errors - ordinary files (100 - 199) +#define Parser_100 "Functions are only defined for batch or triangular batch places" +#define Parser_101 "The flow parameter are only defined for triangular batch places" +#define Parser_102 "The flow parameter must be defined for triangular batch places" +#define Parser_103 "The marking of batches or triangular batches is a list of batches" +#define Parser_104 "The marking of discrete places is an integer" +#define Parser_105 "The marking of discrete places is a float" +#define Parser_106 "Transition arc destination doesn't exist" +#define Parser_107 "Place arc destination doesn't exist" +#define Parser_108 "Bad arc destination (no arc allowed from batch/triangular batch place and discrete transition)" +#define Parser_109 "Place or transition doesn't exist" +#define Parser_110 "Transition doesn't exist" +#define Parser_111 "Place doesn't exist" +#define Parser_112 "Speed modification are only allowed for triangular batch places" +#define Parser_113 "Flow modification are only allowed for continuous or batch transitions" +#define Parser_114 "Wrong interval (final limit appears before initial)." +#define Parser_115 "Bad destination state (this operation cannot be used with the \'from\' primitive)" +#define Parser_116 "Bad destination state (this operation can be used only in a replicated state)" + +// Programming Errors (200 - 299) +#define Parser_200 "Out of range (see FUNCTION define)." +#define Parser_201 "Index out of range." +#define Parser_202 "Can not alloc memory." + + +#endif diff --git a/src/interf/glc.y b/src/interf/glc.y new file mode 100644 index 0000000..35b7e21 --- /dev/null +++ b/src/interf/glc.y @@ -0,0 +1,773 @@ +%{ +//====================================================================================// +// // +// Parser and Semantic Analysis // +// // +//====================================================================================// +// This File: glc.y Tool: YACC // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 15/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 15/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +// YACC is a general-purpose parser generator that converts a context-free grammar // +// a C program.In this module are make the actions to generate the internal SAN's // +// tables and the others functionalities of this textual interface for PEPS. // +//====================================================================================// +#include "bpnfile.h" +#include "simuleau.h" + +//====================================================================================// +// Global variables // +//====================================================================================// + +extern BPN *bpn; // Network structure +extern Schedule *schedule; // schedule structure + +int not_error = 1; +int is_integer = 1; + +int tour; // Set the times that the parser was called, the first to count the number + // of places, the number of transitions and others + +//====================================================================================// +// Variables // +//====================================================================================// + + int discreteplaces; // number of discrete places + int continuousplaces; // number of continuous places + int batchplaces; // number of batch places + int triangularplaces; // number of triangular batch places + + int currentdiscreteplace; // index of the current discrete place used to add place + int currentcontinuousplace; // index of the current continuous place + int currentbatchplace; // index of the current batch place + int currenttriangularplace; // index of the current triangular batch place + + int discretetransitions; // number of discrete transitions + int continuoustransitions; // number of continuous transitions + int batchtransitions; // number of batch transitions + + int currentdiscretetransition; // index of the current discrete place used to add place + int currentcontinuoustransition;// index of the current continuous place + int currentbatchtransition; // index of the current batch place + + place_id idplacenumber; // number of the place id + simuleau_name idplace; // name of the place id + place_type ptype; // place type + double pdensity; // place density + double pspeed; // place speed + double plength; // place length + double pflow; // place flow + + double bdensity; // batch density + double bspeed; // batch speed + double blength; // batch length + double bposition; // batch position + + trans_id idtransitionnumber; // number of the transition id + simuleau_name idtransition; // name of the transition id + trans_type ttype; // transition type + double ttime; // time of the discrete transitions + double tsteadytime; // steady time of the discrete transitions + double tflow; // flow of the continuous and batch transitions + double tsteadyflow; // steady flow of the continuous and batch transitions + + double arcweight; // arc weight + + simuleau_name idcevent; // name of the controlled event + ev_type cetype; // type of the controlled event + simuleau_name idnode; // name of the place or transition + double cedate; // controlled event date + double cevalue; // new value of the flow/speed + + simuleau_name idbreakpoint; // name of the breakpoint + breakpoint_type bptype; // type of the breakpoint (at (?) or every (*)) + double bpdate; // date or frequency + + +//====================================================================================// +// Parser variables // +//====================================================================================// + +extern int yynerrs; // Variable of the YACC generator to count the number of errors. +extern int yylineno; // Variable of the YACC generator to count the current line + +extern int yylex(void); // Get the next token +extern void yyrestart(FILE *input_file); +extern char *yytext; +extern FILE *yyin; // Input file + + +//====================================================================================// +// Function errors // +//====================================================================================// +// These functions analysis which error occurred and put the error into a message // +// more specific. // +//====================================================================================// + + +//==================================================================================== +// Function that YACC use to put syntatic message errors +//==================================================================================== +extern void yyerror(string s) +{ + yynerrs++; + not_error = 0; + Syntatic_Error(yynerrs, yylineno, s, yytext); +} + +//==================================================================================== +// Function to put semantic error messages +//==================================================================================== +void type_error(char* text, const char* error_number) +{ + yynerrs++; + not_error = 0; + Semantic_Error_YACC(yynerrs, yylineno, text, error_number); +} + + +%} + + //-----------------------------------------------------------// + // Definition of tokens (terminals) of the grammar. // + // YACC used these definitions to generate the file // + // y.tab.h that is included in a LEX file (tokens.l) // + //-----------------------------------------------------------// + +%token TK_ARC TK_BATCH TK_CONTINUOUS TK_CONTROLLED TK_DESCRIPTION +%token TK_DISCRETE TK_EVENTS TK_FLOW TK_FUNCTION TK_INITIAL TK_INSPECTION +%token TK_LENGTH TK_MARKING TK_MODEL TK_NETWORK TK_OUTPUT TK_PLACE +%token TK_PLACES TK_SPEED TK_STEADY TK_TIME TK_TIMING TK_TRANSITION TK_TRANSITIONS +%token TK_TRIANGULAR TK_UNITY TK_ID TK_INTEGER TK_REAL TK_EXPONENT TK_AT +%token TK_EVERY TK_LEFT_BRACKET TK_RIGHT_BRACKET TK_PL_TR TK_ALL +%token TK_LEFT_PARENTHESIS TK_RIGHT_PARENTHESIS +%token TK_LEFT_SQUARE_BRACKET TK_RIGHT_SQUARE_BRACKET +%token TK_SEMICOLON TK_COMMA TK_ATTRIB TK_COLON + +%% + + //-----------------------------------------------------------// + // Begin of grammar // + //-----------------------------------------------------------// + +start:blk_def blk_net blk_controlled_events blk_time_inspection + ; + + //-----------------------------------------------------------// + // Block of definitions (model name, length and time unity) // + //-----------------------------------------------------------// + +blk_def: + blk_model blk_unity + ; + +blk_model: + TK_MODEL TK_ID {if (tour == 1) bpn->PutName(yytext);} semi_colon + | + ; + +blk_unity: + blk_lenght blk_time + ; + +blk_lenght: + TK_LENGTH TK_UNITY TK_ATTRIB TK_ID {PRF::prf.Length_Unity(yytext);} semi_colon + | + ; + +blk_time: + TK_TIME TK_UNITY TK_ATTRIB TK_ID {PRF::prf.Time_Unity(yytext);} semi_colon + | + ; + +semi_colon: + TK_SEMICOLON + | + ; + +number: + TK_REAL { is_integer = 0; } + |TK_INTEGER { is_integer = 1; } + |TK_EXPONENT { is_integer = 0; } + ; + + + //-----------------------------------------------------------// + // Block to network description // + //-----------------------------------------------------------// + +blk_net: + TK_NETWORK TK_DESCRIPTION blk_places blk_transitions + ; + +blk_places: + TK_PLACES { cout << "Compiling places\n";} blk_place + ; + +blk_transitions: + TK_TRANSITIONS { cout << "Compiling transitions\n";} blk_transition + ; + + + //-----------------------------------------------------------// + // Block to place description // + //-----------------------------------------------------------// + +blk_place: + TK_PLACE TK_ID + { strcpy(idplace,yytext); + if (tour == 1) { + if (bpn->VerifyName(idplace)) + type_error(idplace, Parser_00); + } + } TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS + blk_function + { if (tour == 1) { + Place *newp; + switch (ptype) { + case Discrete_pl : newp = new DiscretePlace(idplace); + bpn->AddPlace(currentdiscreteplace, newp); + currentdiscreteplace++; + break; + case Continuous_pl : newp = new ContinuousPlace(idplace); + bpn->AddPlace(currentcontinuousplace, newp); + currentcontinuousplace++; + break; + case Batch_pl : newp = new BatchPlace(idplace, pspeed, pdensity, plength); + bpn->AddPlace(currentbatchplace, newp); + currentbatchplace++; + break; + case Triangular_pl : newp = new TriangularBatchPlace(idplace, pspeed, pdensity, plength, pflow); + bpn->AddPlace(currenttriangularplace, newp); + currenttriangularplace++; + break; + } + } + } blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + ; + +blk_place2: + blk_place + | + ; + +blk_place_type: + TK_DISCRETE { discreteplaces++; ptype = Discrete_pl; } + | TK_CONTINUOUS { continuousplaces++; ptype = Continuous_pl; } + | TK_BATCH { batchplaces++; ptype = Batch_pl; } + | TK_TRIANGULAR{ triangularplaces++; ptype = Triangular_pl;} + ; + + //-----------------------------------------------------------// + // Block to function description for batch places // + //-----------------------------------------------------------// + +blk_function: + TK_FUNCTION { if ((ptype != Batch_pl) && (ptype != Triangular_pl)) { + type_error(yytext, Parser_100); + } + } TK_LEFT_PARENTHESIS number { pspeed = atof(yytext); } + TK_COMMA number { pdensity = atof(yytext); } + TK_COMMA number { plength = atof(yytext); } blk_triangular_place TK_RIGHT_PARENTHESIS + | + ; + +blk_triangular_place: + TK_COMMA number { if (ptype != Triangular_pl) { + type_error(yytext, Parser_101); + } + pflow = atof(yytext); } + | { if (ptype == Triangular_pl) { + yyerror(Parser_102); + } + } + ; + //-----------------------------------------------------------// + // Block to initial marking description // + //-----------------------------------------------------------// + +blk_initial_marking: + TK_INITIAL TK_MARKING TK_LEFT_BRACKET blk_initial_marking_int TK_RIGHT_BRACKET + ; + +blk_initial_marking_int: + number + { if (tour == 1){ + switch (ptype) { + case Discrete_pl : if (!is_integer){ + type_error(yytext, Parser_104); + } + else{ + bpn->SetInitialMarking((currentdiscreteplace-1), atoi(yytext)); + } + break; + case Continuous_pl : bpn->SetInitialMarking((currentcontinuousplace-1), atof(yytext)); + break; + case Batch_pl : + case Triangular_pl : type_error(yytext, Parser_103); + break; + } + } + } + | blk_batch + ; + +blk_batch: + TK_LEFT_PARENTHESIS number { blength = atof(yytext); } TK_COMMA number { bdensity = atof(yytext); } + TK_COMMA number { bposition = atof(yytext); } blk_triangular_batch TK_RIGHT_PARENTHESIS + { if (tour == 1){ + Batch *newb; + ControllableBatch *newcb; + switch (ptype) { + case Discrete_pl : type_error(yytext, Parser_104); + break; + case Continuous_pl : type_error(yytext, Parser_105); + break; + case Batch_pl : newb = new Batch(blength, bdensity, bposition); + bpn->AddBatchToInitialMarking((currentbatchplace-1), *newb); + break; + case Triangular_pl : newcb = new ControllableBatch(blength, bdensity, bposition, bspeed); + bpn->AddTriangularToInitialMarking((currenttriangularplace-1), *newcb); + break; + } + } + } blk_batch2 + | + ; + +blk_batch2: + TK_COMMA blk_batch + | + ; + +blk_triangular_batch: + TK_COMMA number { bspeed = atof(yytext); } + | { bspeed = -1;} + ; + + //-----------------------------------------------------------// + // Block to steady marking description // + //-----------------------------------------------------------// + +blk_steady_marking: + TK_STEADY TK_MARKING TK_LEFT_BRACKET blk_steady_marking_int TK_RIGHT_BRACKET + | + ; + +blk_steady_marking_int: + number + { if (tour == 1){ + switch (ptype) { + case Discrete_pl : if (!is_integer){ + type_error(yytext, Parser_104); + } + else{ + bpn->SetSteadyMarking((currentdiscreteplace-1), atoi(yytext)); + } + break; + case Continuous_pl : bpn->SetSteadyMarking((currentcontinuousplace-1), atof(yytext)); + break; + case Batch_pl : + case Triangular_pl : type_error(yytext, Parser_103); + break; + } + } + } + | blk_steady_batch + ; + +blk_steady_batch: + TK_LEFT_PARENTHESIS number { blength = atof(yytext); } TK_COMMA number { bdensity = atof(yytext); } + TK_COMMA number { bposition = atof(yytext); } blk_steady_triangular_batch TK_RIGHT_PARENTHESIS + { if (tour == 1){ + Batch *newb; + ControllableBatch *newcb; + switch (ptype) { + case Discrete_pl : type_error(yytext, Parser_104); + break; + case Continuous_pl : type_error(yytext, Parser_105); + break; + case Batch_pl : newb = new Batch(blength, bdensity, bposition); + bpn->AddBatchToSteadyMarking((currentbatchplace-1), *newb); + break; + case Triangular_pl : newcb = new ControllableBatch(blength, bdensity, bposition, bspeed); + bpn->AddTriangularToSteadyMarking((currenttriangularplace-1), *newcb); + break; + } + } + } blk_steady_batch2 + | + ; + +blk_steady_batch2: + TK_COMMA blk_steady_batch + | + ; + +blk_steady_triangular_batch: + TK_COMMA number { bspeed = atof(yytext); } + | { bspeed = -1;} + ; + + //-----------------------------------------------------------// + // Block to place arcs description // + //-----------------------------------------------------------// + +blk_place_arcs: + TK_OUTPUT TK_ARC TK_ID { strcpy (idtransition, yytext); } blk_place_weight + { if (tour == 2){ + idplacenumber = bpn->GetPlacePosition(idplace); + idtransitionnumber = bpn->GetTransitionPosition(idtransition); + if (idtransitionnumber < 0){ + type_error(idtransition, Parser_106); + } + else{ + if ((bpn->GetTransitionType(idtransition) == Discrete_tr) && !((bpn->GetPlaceType(idplace) == Discrete_pl) || (bpn->GetPlaceType(idplace) == Continuous_pl))){ + type_error(idtransition, Parser_108); + } + else{ + bpn->AddPlaceOutputArc(idplacenumber, idtransitionnumber, arcweight); + } + } + } + } blk_place_arcs2 + | + ; + +blk_place_arcs2: + blk_place_arcs + ; + +blk_place_weight: + TK_LEFT_PARENTHESIS number { arcweight = atof(yytext); } TK_RIGHT_PARENTHESIS + | {arcweight = 1.0;} + ; + + + + //-----------------------------------------------------------// + // Block to transition description // + //-----------------------------------------------------------// + +blk_transition: + TK_TRANSITION TK_ID + { strcpy(idtransition,yytext); + if (tour == 1) { + if (bpn->VerifyName(idtransition)) + type_error(idtransition, Parser_01); + } + } TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS + blk_transition_function + { tsteadytime = 0.0; + tsteadyflow = 0.0; + } + blk_steady_transition_function + { if (tour == 1) { + Transition *newt; + switch (ttype) { + case Discrete_tr : newt = new DiscreteTransition(idtransition, ttime, tsteadytime); + bpn->AddTransition(currentdiscretetransition, newt); + currentdiscretetransition++; + break; + case Continuous_tr : newt = new ContinuousTransition(idtransition, tflow, tsteadyflow); + bpn->AddTransition(currentcontinuoustransition, newt); + currentcontinuoustransition++; + break; + case Batch_tr : newt = new BatchTransition(idtransition, tflow, tsteadyflow); + bpn->AddTransition(currentbatchtransition, newt); + currentbatchtransition++; + break; + } + } + } + blk_transition_arcs blk_transition2 + ; + +blk_transition2: + blk_transition + | + ; + +blk_transition_type: + TK_DISCRETE {discretetransitions++; ttype = Discrete_tr; } + | TK_CONTINUOUS {continuoustransitions++; ttype = Continuous_tr; } + | TK_BATCH {batchtransitions++; ttype = Batch_tr; } + ; + +blk_transition_function: + TK_TIMING TK_LEFT_PARENTHESIS number { ttime = atof(yytext); } TK_RIGHT_PARENTHESIS + | TK_FLOW TK_LEFT_PARENTHESIS number { tflow = atof(yytext); } TK_RIGHT_PARENTHESIS + ; + +blk_steady_transition_function: + TK_STEADY blk_steady_transition_function_int + | + ; + +blk_steady_transition_function_int: + TK_TIMING TK_LEFT_PARENTHESIS number { tsteadytime = atof(yytext); } TK_RIGHT_PARENTHESIS + | TK_FLOW TK_LEFT_PARENTHESIS number { tsteadyflow = atof(yytext); } TK_RIGHT_PARENTHESIS + ; + + + //-----------------------------------------------------------// + // Block to transition arcs description // + //-----------------------------------------------------------// + + +blk_transition_arcs: + TK_OUTPUT TK_ARC TK_ID { strcpy (idplace, yytext); } blk_transition_weight + { if (tour == 2){ + idtransitionnumber = bpn->GetTransitionPosition(idtransition); + idplacenumber = bpn->GetPlacePosition(idplace); + if (idplacenumber < 0){ + type_error(idplace, Parser_107); + } + else{ + bpn->AddTransitionOutputArc(idtransitionnumber, idplacenumber, arcweight); + } + } + } blk_transition_arcs2 + | + ; + +blk_transition_arcs2: + blk_transition_arcs + ; + +blk_transition_weight: + TK_LEFT_PARENTHESIS number { arcweight = atof(yytext); } TK_RIGHT_PARENTHESIS + | {arcweight = 1.0;} + ; + + //-----------------------------------------------------------// + // Block to evaluation of controlled events // + //-----------------------------------------------------------// + +blk_controlled_events: + TK_CONTROLLED TK_EVENTS { cout << "Compiling controlled events\n";} controlled_events + | + ; + +controlled_events: + TK_ID { strcpy(idcevent,yytext); } TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID { strcpy(idnode, yytext); } + TK_COMMA number { cevalue = atof(yytext); } TK_COMMA number { cedate = atof(yytext); } TK_RIGHT_PARENTHESIS semi_colon + { + if (tour == 1){ + Node *evnode = bpn->GetNode(idnode); + ControlledEvent *ev; + if (evnode){ + switch (cetype){ + case Trans_flow_ce : if (bpn->GetTransitionPosition(idnode) == -1){ + type_error(idnode, Parser_110); + } + else{ + if (bpn->GetTransitionType(idnode) == Discrete_tr) { + type_error(idnode, Parser_113); + } + else{ + ev = new ControlledEvent(idnode, *evnode, cedate, Trans_flow_ce, cevalue, idcevent); + schedule->AddControlledEvent(*ev, Trans_flow_ce); + } + } + break; + case Place_speed_ce : if (bpn->GetPlacePosition(idnode) == -1){ + type_error(idnode, Parser_111); + } + else{ + if (bpn->GetPlaceType(idnode) != Triangular_pl) { + type_error(idnode, Parser_112); + } + else{ + ev = new ControlledEvent(idnode, *evnode, cedate, Place_speed_ce, cevalue, idcevent); + schedule->AddControlledEvent(*ev, Place_speed_ce); + } + } + break; + } + } + else{ + type_error(idnode, Parser_109); + } + } + } controlled_events2 + | + ; + +controlled_events2: + controlled_events + ; + +controlled_events_type: + TK_FLOW { cetype = Trans_flow_ce; } + | TK_SPEED {cetype = Place_speed_ce; } + ; + + //-----------------------------------------------------------// + // Block to evaluation of time inspection // + //-----------------------------------------------------------// + +blk_time_inspection: + TK_TIME TK_INSPECTION { cout << "Compiling inspection points\n";} time_inspection + | + ; + +time_inspection: + TK_ID { strcpy(idbreakpoint,yytext); } TK_ATTRIB blk_op_time number { bpdate = atof(yytext); } blk_op_pt { strcpy(idnode, yytext); } semi_colon + { + if (tour == 1){ + Node *bpnode = bpn->GetNode(idnode); + Breakpoint *bp; + if ((bpnode) || (!strcmp(idnode, "places")) || (!strcmp(idnode, "transitions"))){ + bp = new Breakpoint(idnode, *bpnode, bpdate, bptype, idbreakpoint); + schedule->AddBreakpoint(*bp); + } + else{ + type_error(idnode, Parser_109); + } + } + } + time_inspection2 + | + ; + +time_inspection2: + time_inspection + ; + +blk_op_time: + TK_AT { bptype = at_bp; } + | TK_EVERY { bptype = every_bp; } + ; + +blk_op_pt: + TK_PL_TR TK_ID + | TK_ALL blk_pl_tr + ; + +blk_pl_tr: + TK_PLACES + | TK_TRANSITIONS + ; + +%% + + +void Init_Variables() +{ + yylineno = 0; + + //current place/transition + currentdiscreteplace = 0; + currentcontinuousplace = discreteplaces; + currentbatchplace = continuousplaces + discreteplaces; + currenttriangularplace = batchplaces + continuousplaces + discreteplaces; + + currentdiscretetransition = 0; + currentcontinuoustransition = discretetransitions; + currentbatchtransition = continuoustransitions + discretetransitions; +} + + +//int main(int argv, char *argc[]) +void Compile_Network(const simuleau_name bpn_level_name, const simuleau_name str_level_name) +{ + int totalplaces; + int totaltransitions; + ofstream fstr; + simuleau_name bpn_file; + + + strcpy(bpn_file, bpn_level_name); strcat(bpn_file,".bpn"); + + + //first tour: semantical analysis and number of places and transitions + tour = 0; + //counters + discreteplaces = 0; + continuousplaces = 0; + batchplaces = 0; + triangularplaces = 0; + + discretetransitions = 0; + continuoustransitions = 0; + batchtransitions = 0; + + Init_Variables(); + yyin = fopen(bpn_file, "r"); + cout << "Start model compilation\n\n"; + + cout << "First turn\n" + << "==========\n"; + cout << "Creating places and transitions structures\n"; + cout << "Creating controlled events schedule\n"; + yyparse(); + fclose(yyin); + + totalplaces = discreteplaces + continuousplaces + batchplaces + triangularplaces; + totaltransitions = discretetransitions + continuoustransitions + batchtransitions; + + if (bpn!=NULL) + delete bpn; + bpn = new BPN(totalplaces, totaltransitions); + + if (schedule!=NULL) + delete schedule; + schedule = new Schedule; + + // places initialisation + bpn->NumberOfDiscretePlaces(discreteplaces); + bpn->NumberOfContinuousPlaces(continuousplaces); + bpn->NumberOfBatchPlaces(batchplaces); + bpn->NumberOfTriangularBatchPlaces(triangularplaces); + + // transitions initialisation + bpn->NumberOfDiscreteTransitions(discretetransitions); + bpn->NumberOfContinuousTransitions(continuoustransitions); + bpn->NumberOfBatchTransitions(batchtransitions); + + + // second tour + if(!not_error){ + exit (EXIT_FAILURE); + } + + cout << "\nSecond turn\n" + << "===========\n"; + cout << "Initialising places and transitions parameters\n"; + tour++; + Init_Variables(); + yyin = fopen(bpn_file, "r"); + yyrestart(yyin); + yyparse(); + fclose(yyin); + + + // thrid tour + if(!not_error){ + exit (EXIT_FAILURE); + } + + cout << "\nThrid turn\n" + << "==========\n"; + cout << "Initialising places and transitions arcs\n"; + tour++; + bpn->AllocArcs(); + Init_Variables(); + yyin = fopen(bpn_file, "r"); + yyrestart(yyin); + yyparse(); + fclose(yyin); + bpn->AddNodeLinks(); + if(!not_error){ + exit (EXIT_FAILURE); + } + + cout << endl << bpn->GetName() << " model created\n"; + + Open_File(str_level_name, str_file, fstr); + bpn->Print(fstr); + Close_File(str_level_name, str_file, fstr); +} diff --git a/src/interf/interf.cpp b/src/interf/interf.cpp new file mode 100644 index 0000000..34c0fb1 --- /dev/null +++ b/src/interf/interf.cpp @@ -0,0 +1,690 @@ +//====================================================================================// +// // +// SIMULEAU User Interface // +// // +//====================================================================================// +// This File: interf.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 12/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 12/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + + + extern BPN *bpn; + extern Schedule *schedule; + extern Simulate *simulation; + +//====================================================================================// +// Simuleau Name Definitions // +//====================================================================================// + +const simuleau_name no_name = "\0"; // Default empty value for simuleau_name + +//====================================================================================// +// Internal Function Add_Extension // +//====================================================================================// +void Add_Extension(const simuleau_name file, const file_types ft, simuleau_name tmp) +{ + strcpy(tmp, file); + switch (ft) { + case bpn_file : strcat(tmp, ".bpn"); + break; + case str_file : strcat(tmp, ".str"); + break; + case xct_file : strcat(tmp, ".xct"); + break; + case dyn_file : strcat(tmp, ".dyn"); + break; + case tim_file : strcat(tmp, ".tim"); + break; + case dbg_file : strcat(tmp, ".dbg"); + break; + case prf_file : strcat(tmp, ".prf"); + break; + case dot_file : // no extension! + break; + default : strcat(tmp, ".err"); + } +} +//====================================================================================// +// Open_File (to input) // +//====================================================================================// +void Open_File(const simuleau_name file, const file_types ft, ifstream & f_tmp) +{ + simuleau_name n_tmp; + + Add_Extension(file, ft, n_tmp); + + // f_tmp.open(n_tmp, ios::nocreate); + f_tmp.open(n_tmp); + if (!f_tmp) + cerr << "System Error - Cannot open the file '" << n_tmp << "' (#### 0001 ####)" << endl; + else + f_tmp.precision(simuleau_precision); +} + +//====================================================================================// +// Open_File (to output) // +//====================================================================================// +void Open_File(const simuleau_name file, const file_types ft, ofstream & f_tmp) +{ + simuleau_name n_tmp; + + Add_Extension(file, ft, n_tmp); + f_tmp.open(n_tmp); + if (!f_tmp) + cerr << "System Error - Cannot open the file '" << n_tmp << "' (#### 0002 ####)" << endl; + else + f_tmp.precision(simuleau_precision); +} +//====================================================================================// +// Append_File (to output) // +//====================================================================================// +void Append_File(const simuleau_name file, const file_types ft, ofstream & f_tmp) +{ + simuleau_name n_tmp; + + Add_Extension(file, ft, n_tmp); + f_tmp.open(n_tmp, ios::app); + if (!f_tmp) + cerr << "System Error - Cannot open the file '" << n_tmp << "' (#### 0003 ####)" << endl; + else + f_tmp.precision(simuleau_precision); +} +//====================================================================================// +// Close_File (to input) // +//====================================================================================// +void Close_File(const simuleau_name file, const file_types ft, ifstream & f_tmp) +{ + simuleau_name n_tmp; + + Add_Extension(file, ft, n_tmp); + f_tmp.close(); + if (!f_tmp) + cerr << "System Error - Cannot close the file '" << n_tmp << "' (#### 0004 ####)" << endl; + else + cout << " :-) file '" << n_tmp << "' read\n"; +} +//====================================================================================// +// Close_File (to output) // +//====================================================================================// +void Close_File(const simuleau_name file, const file_types ft, ofstream & f_tmp) +{ + simuleau_name n_tmp; + + Add_Extension(file, ft, n_tmp); + f_tmp.close(); + if (!f_tmp) + cerr << "System Error - Cannot close the file '" << n_tmp << "' (#### 0005 ####)" << endl; + else + cout << " :-) file '" << n_tmp << "' saved\n"; +} +//====================================================================================// +// Exists_File // +//====================================================================================// +bool Exists_File(const simuleau_name file, const file_types ft) +{ + ifstream f_tmp; + simuleau_name n_tmp; + + Add_Extension(file, ft, n_tmp); + // f_tmp.open(n_tmp, ios::nocreate); + f_tmp.open(n_tmp); + if (f_tmp) { + return(true); + f_tmp.close(); + } + else + return(false); +} + +//====================================================================================// +// Create Temporary Directories // +//====================================================================================// +void Create_Temporary_Directories() +{ + struct stat st; + if(stat("str",&st) != 0){ + if (mkdir("str", S_IRWXU | S_IRWXG | S_IRWXO)) { + cerr << "System Error - Cannot create directory '" << "str" << "' (#### 0006 ####)" << endl; + } + } + if(stat("dbg",&st) != 0){ + if (mkdir("dbg", S_IRWXU | S_IRWXG | S_IRWXO)) { + cerr << "System Error - Cannot create directory '" << "dbg" << "' (#### 0006 ####)" << endl; + } + } + if(stat("dyn",&st) != 0){ + if (mkdir("dyn", S_IRWXU | S_IRWXG | S_IRWXO)) { + cerr << "System Error - Cannot create directory '" << "dyn" << "' (#### 0006 ####)" << endl; + } + } +} +//====================================================================================// +// Remove Temporary Directories // +//====================================================================================// +void Remove_Temporary_Directories() +{ + system("rm -rf str"); + system("rm -rf dbg"); + system("rm -rf dyn"); +} +//====================================================================================// +// Remove Probability Vectors // +//====================================================================================// +void Remove_Dynamics_Files() +{ + system("rm -f dyn/*.dyn"); +} +//====================================================================================// +// Remove Tim Files // +//====================================================================================// +void Remove_Tim_Files() +{ + system("rm -f *.tim"); +} + +//====================================================================================// +// Ask_a_File_Name // +//====================================================================================// +void Ask_a_File_Name(simuleau_name & name, const file_types ft) +{ + cout << "\nEnter "; + switch (ft) { + case bpn_file : cout << "textual BPN"; + break; + case str_file : cout << "internal representation of BPN structure"; + break; + case xct_file : cout << "textual external controlled events"; + break; + case dyn_file : cout << "dynamics log"; + break; + case tim_file : cout << "time report"; + break; + case dbg_file : cout << "debugging"; + break; + case prf_file : cout << "user preferences"; + break; + default : cout << "unrecognized"; + } + cout << " file name: "; + cin >> name; +} +//====================================================================================// +// Ask_an_Existing_File_Name // +//====================================================================================// +void Ask_an_Existing_File_Name(simuleau_name & name, const file_types ft) +{ + bool exists; + + do { + Ask_a_File_Name(name, ft); + exists = Exists_File(name, ft); + if (!exists) + cout << "This file can not be found!"; + } while (!exists); +} +//====================================================================================// +// Permission_to_Proceed // +//====================================================================================// +bool Permission_to_Proceed(const simuleau_name name, const file_types ft) +{ + bool answer = true; + char y_n; + simuleau_name tmp; + + if (Exists_File(name, ft)) { + Add_Extension(name, ft, tmp); + cout << "File '" << tmp << "' already exists and will be replaced. " + << "Procede anyway (y/n)? "; + cin >> y_n; + answer = ((y_n == 'y') || (y_n == 'Y')); + cout << "\n"; + } + return(answer); +} + +//====================================================================================// +// Get_Only_the_File_Name // +//====================================================================================// +void Get_Only_the_File_Name(const simuleau_name full_name, simuleau_name & just_the_file_name) +{ + int last_slash_position = -1; + int mark = 0; + + do { + if (full_name[mark] == '/') + last_slash_position = mark; + mark++; + } while (full_name[mark] != '\0'); + strcpy(just_the_file_name, &full_name[last_slash_position+1]); +} + + +//====================================================================================// +// Ask_a_Place // +//====================================================================================// +place_id Ask_a_Place() +{ + simuleau_name name; + place_id i, place; + + cout << "The places are: "; + for (i=0; i<bpn->NumberOfPlaces(); i++) { + cout << "\n " << i << ") " << bpn->GetPlaceName(i); + } + cout << "\n\nChoose a place (enter its index, -1 to show all): "; + cin >> place; + if (place == -1) + return place; + if ( (place < 0) || (place >= bpn->NumberOfPlaces()) ) { + place = fst_place; + cout << "Assuming first place\n"; + } + return place; +} + +//====================================================================================// +// Ask_a_Transition // +//====================================================================================// +trans_id Ask_a_Transition() +{ + simuleau_name name; + trans_id i, trans; + + cout << "The transitions are: "; + for (i=0; i<bpn->NumberOfTransitions(); i++) { + cout << "\n " << i << ") " << bpn->GetTransitionName(i); + } + cout << "\n\nChoose a transition (enter its index, -1 to show all): "; + cin >> trans; + if (trans == -1) + return trans; + if ( (trans < 0) || (trans >= bpn->NumberOfTransitions()) ) { + trans = fst_trans; + cout << "Assuming first transition\n"; + } + return trans; +} + + +//====================================================================================// +// See_BPN // +//====================================================================================// +void See_BPN() +{ + if (simulation != NULL ){ + if (!simulation->IsEmpty()) { + cout << "\n---------------------------------------------------------------" + << "\nInspecting the BPN model and scheduled events" + << "\n---------------------------------------------------------------\n\n"; + simulation->Print(std::cout); + } + } + else{ + cout << "There is no Batch Petri Net model (bpn) in memory.\n" + << "You must compile a bpn using the option 1 in main menu.\n"; + } +} + +//====================================================================================// +// See_place // +//====================================================================================// +void See_place() +{ + place_id placenumber; + BPN *b; + Place *p; + + if ((simulation != NULL)){ + placenumber = Ask_a_Place(); + b = simulation->GetBpn(); + if (placenumber == -1){ + cout << "\n---------------------------------------------------------------" + << "\nInspecting all places" + << "\n---------------------------------------------------------------\n\n"; + + for (int i=0; i<b->NumberOfPlaces(); i++) { + p = b->GetNode(b->GetPlaceName(i)); + p->Print(std::cout); + } + return; + } + cout << "\n---------------------------------------------------------------" + << "\nInspecting place " << b->GetPlaceName(placenumber) + << "\n---------------------------------------------------------------\n\n"; + + p = b->GetNode(b->GetPlaceName(placenumber)); + p->Print(std::cout); + } +} + +//====================================================================================// +// See_trans // +//====================================================================================// +void See_trans() +{ + trans_id transnumber; + BPN *b; + Transition *t; + + if ((simulation != NULL)){ + transnumber = Ask_a_Transition(); + b = simulation->GetBpn(); + if (transnumber == -1){ + cout << "\n---------------------------------------------------------------" + << "\nInspecting all transitions" + << "\n---------------------------------------------------------------\n\n"; + + for (int i=0; i<b->NumberOfTransitions(); i++) { + t = b->GetNode(b->GetTransitionName(i)); + t->Print(std::cout); + } + return; + } + cout << "\n---------------------------------------------------------------" + << "\nInspecting transition " << b->GetTransitionName(transnumber) + << "\n---------------------------------------------------------------\n\n"; + + t = b->GetNode(b->GetTransitionName(transnumber)); + t->Print(std::cout); + } +} + +//====================================================================================// +// See_events // +//====================================================================================// +void See_events() +{ + Schedule *s; + + if ((simulation != NULL)){ + cout << "\n---------------------------------------------------------------" + << "\nInspecting all scheduled events" + << "\n---------------------------------------------------------------\n\n"; + s = simulation->GetSchedule(); + s->Print(std::cout); + } +} + + +//====================================================================================// +// Ask an Answer // +//====================================================================================// +bool Ask_an_Answer(const simuleau_name name) +{ + bool answer = true; + char y_n; + + cout << name << " (y/n)? "; + cin >> y_n; + answer = ((y_n == 'y') || (y_n == 'Y') || (y_n == '0')); + cout << "\n"; + return(answer); +} +//====================================================================================// +// Ask an Error // +//====================================================================================// +double Ask_an_Error() +{ + double error; + + cout << "Enter tolerance: "; + cin >> error; + if (error < 0) { + error = def_err; + cout << "Assuming default value: " << def_err << "\n"; + } + return(error); +} +//====================================================================================// +// Ask an Inspect Time // +//====================================================================================// +double Ask_an_Inspect_Time() +{ + double time; + + cout << "Enter time to inspect: "; + cin >> time; + if (time < 0) { + time = zero; + cout << "Assuming default value: " << zero << "\n"; + } + return(time); +} + +//====================================================================================// +// Ask a Simulation Time // +//====================================================================================// +double Ask_a_Simulation_Time() +{ + double time; + + cout << "Enter maximum simulation time: "; + cin >> time; + if (time <= 0) { + time = def_time; + cout << "Assuming default value: " << def_time << "\n"; + } + return(time); +} + +//====================================================================================// +// Ask a Length Unity // +//====================================================================================// +char* Ask_a_Length_Unity() +{ + simuleau_name length; + + cout << "Enter the lenght unity: "; + cin >> length; + if (!strcmp(length,"0")) { + strcpy(length, def_length_unity); + cout << "Assuming default value: " << def_length_unity << "\n"; + } + return(length); +} + +//====================================================================================// +// Ask a Time Unity // +//====================================================================================// +char* Ask_a_Time_Unity() +{ + simuleau_name time; + + cout << "Enter the time unity: "; + cin >> time; + if (!strcmp(time,"0")) { + strcpy(time, def_time_unity); + cout << "Assuming default value: " << def_time_unity << "\n"; + } + return(time); +} + + +//====================================================================================// +// Notify_Time_Spend (stdout) - translations version // +//====================================================================================// +void Notify_Time_Spend(const Timer T, const simuleau_name op) +{ + ofstream out_file; + + cout << "\nTranslation performed: " << op << endl + << " - user time spent: " << T.usertime() << " seconds\n" + << " - system time spent: " << T.systime() << " seconds\n" + << " - real time spent: " << T.realtime() << " seconds\n"; +} + + +//====================================================================================// +// Show Credits // +//====================================================================================// +void Show_Credits() +{ + cout << "\n\n Simuleau - Simulator of Batch Petri Nets - version 2016 " + << "\n\n Simuleau is a software tool for simulate Batch Petri Nets (BPN)" + << "\n\n The current version (2016) is (still) an experimental version." + << "\n Mathematical basis for BPN may be obtained in the literature." +// << "\n\n Simuleau is a collective software effort and its authors may be" +// << "\n reached at:" +// << "\n simuleau@lsis.org or http://www.lsis.org/spip.php?id_rubrique=385" + << "\n\n The distribution of this software is free. Any comercial use of" + << "\n Simuleauu or modified versions of Simuleau cannot be performed without" + << "\n the formal autorization of the authors. Any scientific benefit of the" + << "\n use of the Simuleau tool must mention it." + << "\n\n This version of Simuleau was released on: " << __RELEASE_DATE__ + << "\n and it has been compiled on: " << __DATE__ +#ifdef _SIMULEAU_DEBUG_ + << " (debug version)\n\n"; +#else + << " (optimized version)\n\n"; +#endif +} +//====================================================================================// +// Say Goodbye // +//====================================================================================// +void Say_Goodbye() +{ + cout << "\n\nThanks for using Simuleau!\n\n"; +} +//====================================================================================// +// Say Sorry // +//====================================================================================// +void Say_Sorry() +{ + cout << "\nI'm sorry this option does not work right now!\n"; +} + +//====================================================================================// +// Welcome_Get_Simuleau_Option // +//====================================================================================// +simuleau_options Welcome_Get_Simuleau_Option() +{ + char option; + simuleau_options answer = nothing; + simuleau_name buf; + + do +{cout << "\n\n +--------------------------------------------------------+" + << "\n | This is Simuleau 2016 - the BPN tool |" + << "\n | released on: " << __RELEASE_DATE__ << " -- compiled on: " << __DATE__ << " |" +#ifdef _SIMULEAU_DEBUG_ + << "\n | *** debug version *** |" +#endif + << "\n +--------------------------------------------------------+" + << "\n\n 1) Compile a BPN model 4) Inspect data structures" + << "\n 2) Simulate a compiled BPN model 5) Dynamics facilities" + << "\n 3) Preferences 6) About this version" + << "\n\n 0) Exit Simuleau (Option 0 always exits the current menu)\n"; + + cin >> option; + switch (option) { + case '1': cout << "\n\n ******* Compiling a BPN Model *******" + << "\n\n 1) Standard Compilation\n"; + cin >> option; + switch (option) { + case '1': answer = compile; break; + } break; + case '2': cout << "\n\n ******* Simulating a BPN model *******" + << "\n\n 1) With controlled events 3) On/Off control method\n" + << " 2) Without conntrolled events 4) MF-On/Off control method\n"; +// << " 4) Computation of steady state 6) Computation of periodic steady state\n"; + + + + + cin >> option; + switch (option) { + case '1': answer = simulate_xct; break; + case '2': answer = simulate; break; + case '3': answer = simulate_onoff; break; + case '4': answer = simulate_mf_onoff; break; + case '5': answer = compute_steadystate; break; + case '6': answer = compute_periodicsteadystate; break; + } break; + case '3': cout << "\n\n ******* Changing Preferences *******" + << "\n\n 1) Verbose Mode: "; + cout << PRF::prf.Sverb(); + cout << "\n 2) Maximum simulation time: " + << PRF::prf.Max_Time(); + cout << "\n 3) Tolerance accepted: " + << PRF::prf.Min_Err(); + cout << "\n 4) Length unity: " + << PRF::prf.Length_Unity(); + cout << "\n 5) Time unity: " + << PRF::prf.Time_Unity(); + cout << "\n\nEnter a number to change the corresponding parameter: "; + cin >> option; + switch (option) { + case '1': PRF::prf.Verb(Ask_an_Answer("Do you want verbose mode")); break; + case '2': PRF::prf.Max_Time(Ask_a_Simulation_Time()); break; + case '3': PRF::prf.Min_Err(Ask_an_Error()); break; + case '4': PRF::prf.Length_Unity(Ask_a_Length_Unity()); break; + case '5': PRF::prf.Time_Unity(Ask_a_Time_Unity()); break; + } break; + case '4': cout << "\n\n ******* Inspect Data Structures *******" + << "\n\n 1) BPN in Memory " + << "\n 2) Place " + << "\n 3) Transition " + << "\n 4) Controlled events\n"; + cin >> option; + switch (option) { + case '1': answer = see_bpn; break; + case '2': answer = see_place; break; + case '3': answer = see_trans; break; + case '4': answer = see_events; } break; +/*case '5': cout << "\n\n ******* Probability Vector Facilities *******" + << "\n\n 1) local state probabilities 5) global state probabilities" + << "\n 2) integrate results 6) compute residue" + << "\n 3) compare two vectors 7) vector characteristics" + << "\n 4) inspect probability vector 8) inspect reachable state space\n" + << "\n 9) import a MARCA vector\n"; + cin >> option; + switch (option) { + case '1': answer = integrate_local; break; + case '2': answer = integrate_results; break; + case '3': answer = compare_vct; break; + case '4': answer = slice_vct; break; + case '5': answer = look_global_vct; break; + case '6': answer = residue_vct; break; + case '7': answer = charac_vct; break; + case '8': answer = analyse_reachable; break; + case '9': answer = import_marca_vct; } break;*/ + case '6': answer = credits; break; + /*case 'd': cout << "\n\n ******* Entering Simuleau 2016 debug mode *******" + << "\n *** i.e., you shouldn't be here ***" + << "\n\n 1) edit inner preferences 5) print rss" + << "\n 2) print dsc 6) print cnd" + << "\n 3) print dct 7) print cnd-diag" + << "\n 4) print ftb 8) print inf" + << "\n 9) Show Structures\n"; + cin >> option; + switch (option) { + case '1': Preferences(); break; + case '2': DSC::dsc.print(); break; + case '3': DCT::dct.print(); break; + case '4': FTB::ftb.print(); break; + case '5': RSS::rss.print(); break; + case '6': CND::cnd.print(); break; + case '7': CND::cnd.dprint(); break; + case '8': INF::inf.print(); break; + case '9': Show_Structures(); } break;*/ + case '0': answer = goodbye; + break; + default : answer = nothing; + break; + } +} + while (answer == nothing); + return(answer); +} + + + + + + + + diff --git a/src/interf/interf.h b/src/interf/interf.h new file mode 100644 index 0000000..3c21ca0 --- /dev/null +++ b/src/interf/interf.h @@ -0,0 +1,152 @@ +//====================================================================================// +// // +// SIMULEAU User Interface // +// // +//====================================================================================// +// This File: interf.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 12/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 12/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef INTERF_H +#define INTERF_H + + +//------------------------------------------------------------------------------------// +// Operations Performed by Simuleau // +//------------------------------------------------------------------------------------// + +enum simuleau_options { // all operations that simuleau can do +//====================================================================================// +//------------------------------- Compiling Operations -------------------------------// +//====================================================================================// + compile , // compile (bpn -> str) + +//====================================================================================// +//--------------------------------- Simule Operations --------------------------------// +//====================================================================================// + simulate , // simulate + simulate_xct , // simulate with external controlled events + simulate_onoff, // simulate with on/off control method + compute_steadystate, //simulate with computation of steady state + simulate_mf_onoff, // simulate with maximal flow based on/off control method + compute_periodicsteadystate, //simulate with computation of periodic steady state + +//====================================================================================// +//--------------------------------- Inspect Operations -------------------------------// +//====================================================================================// + see_bpn , // inspect BPN internal representation + see_place , // inspect a specific place + see_trans , // inspect a specific transition + see_events , // inspect current events + see_dyn , // inspect dynamics + see_tim , // inspect dynamics in a specific instant + +//====================================================================================// +//---------------------------------- Other operations --------------------------------// +//====================================================================================// + credits , // show Simuleau credits + nothing , // do nothing + goodbye }; // exit Simuleau tool + + +//------------------------------------------------------------------------------------// +// Interface Functions used by Simuleau // +//------------------------------------------------------------------------------------// +void Open_File(const simuleau_name file, const file_types ft, ifstream & f_tmp); + +void Open_File(const simuleau_name file, const file_types ft, ofstream & f_tmp); + +void Append_File(const simuleau_name file, const file_types ft, ofstream & f_tmp); + +void Close_File(const simuleau_name file, const file_types ft, ifstream & f_tmp); + +void Close_File(const simuleau_name file, const file_types ft, ofstream & f_tmp); + +bool Exists_File(const simuleau_name file, const file_types ft); + +void Create_Temporary_Directories(); + +void Remove_Temporary_Directories(); + +void Remove_Dynamics_Files(); + +void Remove_Tim_Files(); + +void Ask_a_File_Name(simuleau_name & name, const file_types ft); + +void Ask_an_Existing_File_Name(simuleau_name & name, const file_types ft); + +bool Permission_to_Proceed(const simuleau_name name, const file_types ft); + +void Get_Only_the_File_Name(const simuleau_name full_name, simuleau_name & just_the_file_name); + +place_id Ask_a_Place(); + +trans_id Ask_a_Transition(); + +bool Provide_BPN(); + +bool Provide_XCT(); + +void See_BPN(); + +void See_place(); + +void See_trans(); + +void See_events(); + +void See_DYN(); + +void See_TIM(); + +bool Ask_an_Answer(const simuleau_name name); + +double Ask_an_Error(); + +double Ask_an_Inspect_Time(); + +double Ask_a_Simulation_Time(); + +void Show_User_Preferences(); + +void Change_User_Preferences(); + +void Notify_Time_Spend(const Timer T, const simuleau_name op); + +void Show_Credits(); + +void Say_Goodbye(); + +void Say_Sorry(); + +simuleau_options Welcome_Get_Simuleau_Option(); + +void Show_Structures(); + +void Preferences(); + + +//------------------------------------------------------------------------------------// +// Macro definition of error messages // +//------------------------------------------------------------------------------------// + +#define Programming_Error(text, number) \ + { cerr << "Programming Error - " << text << " (**** " << number << " ****)\n" \ + << "(file '" << __FILE__ << "' - line " << __LINE__ << ")\n" \ + << "****************************************************************\n"; \ + exit(1); } + +#define Programming_Warning(text, number) \ + { cerr << "Programming Warning - " << text << " (++++ " << number << " ++++)\n" \ + << "(file '" << __FILE__ << "' - line " << __LINE__ << ")\n"; } + +#define Compilation_Error(structure, text) \ + { cerr << structure << " Compilation Error - " << text << "\n" \ + << "****************************************************************\n"; \ + exit(1); } + + +#endif // INTERF_H diff --git a/src/interf/lex.yy.c b/src/interf/lex.yy.c new file mode 100644 index 0000000..bee692c --- /dev/null +++ b/src/interf/lex.yy.c @@ -0,0 +1,2152 @@ + +#line 3 "lex.yy.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 0 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +#if defined(__GNUC__) && __GNUC__ >= 3 +__attribute__((__noreturn__)) +#endif +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 49 +#define YY_END_OF_BUFFER 50 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[185] = + { 0, + 46, 46, 50, 48, 46, 47, 33, 38, 39, 35, + 43, 48, 29, 45, 42, 44, 34, 32, 28, 40, + 41, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 36, 37, 46, 1, + 0, 29, 0, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 1, 30, 0, 31, 2, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 9, 28, 28, 28, 28, + + 28, 28, 28, 28, 28, 28, 28, 22, 28, 28, + 28, 28, 3, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 15, 28, 28, 18, 20, 28, 28, + 28, 28, 27, 28, 28, 28, 28, 8, 28, 28, + 28, 13, 28, 28, 17, 19, 21, 23, 28, 28, + 28, 28, 28, 28, 28, 11, 28, 14, 16, 28, + 28, 28, 28, 28, 7, 10, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 4, 5, 28, 12, 24, + 26, 6, 25, 0 + } ; + +static yyconst YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 5, 5, 6, 5, 5, 5, 5, 7, + 8, 9, 10, 11, 10, 12, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 15, 16, 5, + 17, 5, 18, 19, 20, 20, 20, 20, 21, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 22, 5, 23, 5, 20, 1, 24, 25, 26, 27, + + 28, 29, 30, 31, 32, 20, 33, 34, 35, 36, + 37, 38, 20, 39, 40, 41, 42, 43, 44, 20, + 45, 20, 46, 5, 47, 5, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst YY_CHAR yy_meta[48] = + { 0, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, + 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 2, 2 + } ; + +static yyconst flex_uint16_t yy_base[187] = + { 0, + 0, 0, 207, 208, 46, 208, 208, 208, 208, 208, + 208, 193, 37, 208, 208, 208, 208, 208, 0, 208, + 208, 166, 180, 166, 24, 159, 19, 165, 172, 30, + 171, 156, 163, 19, 23, 160, 208, 208, 62, 0, + 181, 56, 49, 0, 168, 152, 156, 151, 150, 161, + 151, 151, 39, 150, 146, 157, 142, 141, 157, 152, + 151, 143, 48, 145, 0, 55, 162, 161, 0, 148, + 132, 146, 145, 134, 125, 142, 126, 128, 135, 131, + 135, 118, 123, 134, 131, 134, 46, 121, 132, 114, + 123, 43, 114, 113, 110, 0, 109, 117, 120, 106, + + 114, 111, 107, 101, 114, 114, 113, 0, 103, 98, + 101, 91, 0, 99, 97, 101, 104, 91, 98, 105, + 102, 96, 90, 0, 86, 83, 83, 0, 77, 91, + 88, 89, 0, 76, 83, 78, 74, 0, 77, 79, + 71, 0, 81, 77, 0, 0, 0, 0, 68, 66, + 70, 72, 64, 76, 67, 0, 70, 0, 0, 69, + 66, 57, 70, 65, 0, 0, 59, 58, 70, 53, + 65, 54, 54, 53, 49, 0, 0, 51, 0, 41, + 0, 0, 0, 208, 70, 83 + } ; + +static yyconst flex_int16_t yy_def[187] = + { 0, + 184, 1, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 185, 184, + 184, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 184, 184, 184, 186, + 184, 184, 184, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 186, 184, 184, 184, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 0, 184, 184 + } ; + +static yyconst flex_uint16_t yy_nxt[256] = + { 0, + 4, 5, 6, 5, 4, 7, 8, 9, 10, 4, + 11, 4, 12, 13, 14, 15, 16, 17, 18, 19, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 19, + 19, 28, 19, 29, 30, 31, 32, 33, 19, 34, + 35, 36, 19, 19, 19, 37, 38, 39, 41, 39, + 42, 48, 51, 55, 62, 49, 60, 43, 67, 61, + 52, 63, 68, 39, 43, 39, 56, 41, 66, 42, + 77, 88, 44, 108, 114, 43, 43, 109, 78, 89, + 183, 115, 43, 43, 65, 65, 182, 181, 180, 179, + 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, + + 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, + 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, + 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, + 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, + 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, + 118, 117, 116, 113, 112, 111, 110, 107, 106, 105, + 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, + 94, 93, 92, 91, 68, 68, 90, 87, 86, 85, + 84, 83, 82, 81, 80, 79, 76, 75, 74, 73, + 72, 71, 70, 69, 66, 64, 59, 58, 57, 54, + + 53, 50, 47, 46, 45, 40, 184, 3, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184 + } ; + +static yyconst flex_int16_t yy_chk[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 5, 13, 5, + 13, 25, 27, 30, 35, 25, 34, 13, 43, 34, + 27, 35, 43, 39, 13, 39, 30, 42, 66, 42, + 53, 63, 185, 87, 92, 66, 42, 87, 53, 63, + 180, 92, 66, 42, 186, 186, 178, 175, 174, 173, + 172, 171, 170, 169, 168, 167, 164, 163, 162, 161, + + 160, 157, 155, 154, 153, 152, 151, 150, 149, 144, + 143, 141, 140, 139, 137, 136, 135, 134, 132, 131, + 130, 129, 127, 126, 125, 123, 122, 121, 120, 119, + 118, 117, 116, 115, 114, 112, 111, 110, 109, 107, + 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, + 95, 94, 93, 91, 90, 89, 88, 86, 85, 84, + 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, + 73, 72, 71, 70, 68, 67, 64, 62, 61, 60, + 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, + 48, 47, 46, 45, 41, 36, 33, 32, 31, 29, + + 28, 26, 24, 23, 22, 12, 3, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "tokens.l" +#line 2 "tokens.l" +//====================================================================================// +// // +// Lexical Analyzer // +// // +//====================================================================================// +// This File: tokens.l Tool: lex // +// Software: SIMULEAU // +// Doc: // +//====================================================================================// +// Creation: 15/Apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 15/Apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +// This file has the definitions of the tokens that must to be recognized by the // +// grammar contained in the "glc.y" file. These definitions are used by LEX tool, // +// which is a generator of lexical parsers. // +// The lexical analyzer (scanner) is a function that reads an input stream and // +// returns the correspondents tokens. // +//====================================================================================// +#include "bpnfile.h" + +extern int yynerrs; // Variable of the YACC generator to count the number of errors. +extern int yylineno; + +//====================================================================================// +// Below are defined the R.E.(Regular Expressions) that defines the format of the // +// digits (symbols between 0 and 9, inclusively), integers, reals, exponents and // +// identifies. The symbol "+" indicate one or more occurrences, the symbol "*" // +// indicate zero or more occurrences and the symbol "?" indicate that the occurrence // +// is optional. // +//====================================================================================// + +#line 612 "lex.yy.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * _in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * _out_str ); + +yy_size_t yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + +#ifndef YY_NO_UNPUT + + static void yyunput (int c,char *buf_ptr ); + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + { +#line 41 "tokens.l" + + +#line 833 "lex.yy.c" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 185 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 208 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 43 "tokens.l" + + YY_BREAK +case 2: +YY_RULE_SETUP +#line 44 "tokens.l" +{return(TK_ARC);} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 45 "tokens.l" +{return(TK_BATCH);} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 46 "tokens.l" +{return(TK_CONTINUOUS);} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 47 "tokens.l" +{return(TK_CONTROLLED);} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 48 "tokens.l" +{return(TK_DESCRIPTION);} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 49 "tokens.l" +{return(TK_DISCRETE);} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 50 "tokens.l" +{return(TK_EVENTS);} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 51 "tokens.l" +{return(TK_FLOW);} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 52 "tokens.l" +{return(TK_FUNCTION);} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 53 "tokens.l" +{return(TK_INITIAL);} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 54 "tokens.l" +{return(TK_INSPECTION);} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 55 "tokens.l" +{return(TK_LENGTH);} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 56 "tokens.l" +{return(TK_MARKING);} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 57 "tokens.l" +{return(TK_MODEL);} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 58 "tokens.l" +{return(TK_NETWORK);} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 59 "tokens.l" +{return(TK_OUTPUT);} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 60 "tokens.l" +{return(TK_PLACE);} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 61 "tokens.l" +{return(TK_PLACES);} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 62 "tokens.l" +{return(TK_SPEED);} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 63 "tokens.l" +{return(TK_STEADY);} + YY_BREAK +case 22: +YY_RULE_SETUP +#line 64 "tokens.l" +{return(TK_TIME);} + YY_BREAK +case 23: +YY_RULE_SETUP +#line 65 "tokens.l" +{return(TK_TIMING);} + YY_BREAK +case 24: +YY_RULE_SETUP +#line 66 "tokens.l" +{return(TK_TRANSITION);} + YY_BREAK +case 25: +YY_RULE_SETUP +#line 67 "tokens.l" +{return(TK_TRANSITIONS);} + YY_BREAK +case 26: +YY_RULE_SETUP +#line 68 "tokens.l" +{return(TK_TRIANGULAR);} + YY_BREAK +case 27: +YY_RULE_SETUP +#line 69 "tokens.l" +{return(TK_UNITY);} + YY_BREAK +case 28: +YY_RULE_SETUP +#line 70 "tokens.l" +{return(TK_ID);} + YY_BREAK +case 29: +YY_RULE_SETUP +#line 71 "tokens.l" +{return(TK_INTEGER);} + YY_BREAK +case 30: +YY_RULE_SETUP +#line 72 "tokens.l" +{return(TK_REAL);} + YY_BREAK +case 31: +YY_RULE_SETUP +#line 73 "tokens.l" +{return(TK_EXPONENT);} + YY_BREAK +case 32: +YY_RULE_SETUP +#line 74 "tokens.l" +{return(TK_AT);} + YY_BREAK +case 33: +YY_RULE_SETUP +#line 75 "tokens.l" +{return(TK_EVERY);} + YY_BREAK +case 34: +YY_RULE_SETUP +#line 76 "tokens.l" +{return(TK_PL_TR);} + YY_BREAK +case 35: +YY_RULE_SETUP +#line 77 "tokens.l" +{return(TK_ALL);} + YY_BREAK +case 36: +YY_RULE_SETUP +#line 78 "tokens.l" +{return(TK_LEFT_BRACKET);} + YY_BREAK +case 37: +YY_RULE_SETUP +#line 79 "tokens.l" +{return(TK_RIGHT_BRACKET);} + YY_BREAK +case 38: +YY_RULE_SETUP +#line 80 "tokens.l" +{return(TK_LEFT_PARENTHESIS);} + YY_BREAK +case 39: +YY_RULE_SETUP +#line 81 "tokens.l" +{return(TK_RIGHT_PARENTHESIS);} + YY_BREAK +case 40: +YY_RULE_SETUP +#line 82 "tokens.l" +{return(TK_LEFT_SQUARE_BRACKET);} + YY_BREAK +case 41: +YY_RULE_SETUP +#line 83 "tokens.l" +{return(TK_RIGHT_SQUARE_BRACKET);} + YY_BREAK +case 42: +YY_RULE_SETUP +#line 84 "tokens.l" +{return(TK_SEMICOLON);} + YY_BREAK +case 43: +YY_RULE_SETUP +#line 85 "tokens.l" +{return(TK_COMMA);} + YY_BREAK +case 44: +YY_RULE_SETUP +#line 86 "tokens.l" +{return(TK_ATTRIB);} + YY_BREAK +case 45: +YY_RULE_SETUP +#line 87 "tokens.l" +{return(TK_COLON);} + YY_BREAK +case 46: +YY_RULE_SETUP +#line 88 "tokens.l" +{/* Ignore the blanks, tabulates and new line */} + YY_BREAK +case 47: +/* rule 47 can match eol */ +YY_RULE_SETUP +#line 89 "tokens.l" +{yylineno++;} + YY_BREAK +case 48: +YY_RULE_SETUP +#line 90 "tokens.l" +{ /* If neither token return, means that the input + stream has a lexical error */ + yynerrs++; + Lexical_Error(yynerrs, yylineno, yytext);} + YY_BREAK +case 49: +YY_RULE_SETUP +#line 94 "tokens.l" +ECHO; + YY_BREAK +#line 1139 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + yy_size_t number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 185 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 185 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 184); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + + static void yyunput (int c, char * yy_bp ) +{ + char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + yy_size_t number_to_move = (yy_n_chars) + 2; + char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = (yy_size_t)size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + yy_size_t i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +yy_size_t yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param _line_number line number + * + */ +void yyset_lineno (int _line_number ) +{ + + yylineno = _line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str ) +{ + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str ) +{ + yyout = _out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int _bdebug ) +{ + yy_flex_debug = _bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 94 "tokens.l" + + + +int yywrap () +{ + return(1); +} + +void go2init() +{ + yy_init = 1; +} + diff --git a/src/interf/lex.yy.cpp b/src/interf/lex.yy.cpp new file mode 100644 index 0000000..ce2def8 --- /dev/null +++ b/src/interf/lex.yy.cpp @@ -0,0 +1,2153 @@ +#line 2 "lex.yy.cpp" + +#line 4 "lex.yy.cpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 0 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +#if defined(__GNUC__) && __GNUC__ >= 3 +__attribute__((__noreturn__)) +#endif +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 49 +#define YY_END_OF_BUFFER 50 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[185] = + { 0, + 46, 46, 50, 48, 46, 47, 33, 38, 39, 35, + 43, 48, 29, 45, 42, 44, 34, 32, 28, 40, + 41, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 36, 37, 46, 1, + 0, 29, 0, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 1, 30, 0, 31, 2, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 9, 28, 28, 28, 28, + + 28, 28, 28, 28, 28, 28, 28, 22, 28, 28, + 28, 28, 3, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 15, 28, 28, 18, 20, 28, 28, + 28, 28, 27, 28, 28, 28, 28, 8, 28, 28, + 28, 13, 28, 28, 17, 19, 21, 23, 28, 28, + 28, 28, 28, 28, 28, 11, 28, 14, 16, 28, + 28, 28, 28, 28, 7, 10, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 4, 5, 28, 12, 24, + 26, 6, 25, 0 + } ; + +static yyconst YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 5, 5, 6, 5, 5, 5, 5, 7, + 8, 9, 10, 11, 10, 12, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 15, 16, 5, + 17, 5, 18, 19, 20, 20, 20, 20, 21, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 22, 5, 23, 5, 20, 1, 24, 25, 26, 27, + + 28, 29, 30, 31, 32, 20, 33, 34, 35, 36, + 37, 38, 20, 39, 40, 41, 42, 43, 44, 20, + 45, 20, 46, 5, 47, 5, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst YY_CHAR yy_meta[48] = + { 0, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, + 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 2, 2 + } ; + +static yyconst flex_uint16_t yy_base[187] = + { 0, + 0, 0, 207, 208, 46, 208, 208, 208, 208, 208, + 208, 193, 37, 208, 208, 208, 208, 208, 0, 208, + 208, 166, 180, 166, 24, 159, 19, 165, 172, 30, + 171, 156, 163, 19, 23, 160, 208, 208, 62, 0, + 181, 56, 49, 0, 168, 152, 156, 151, 150, 161, + 151, 151, 39, 150, 146, 157, 142, 141, 157, 152, + 151, 143, 48, 145, 0, 55, 162, 161, 0, 148, + 132, 146, 145, 134, 125, 142, 126, 128, 135, 131, + 135, 118, 123, 134, 131, 134, 46, 121, 132, 114, + 123, 43, 114, 113, 110, 0, 109, 117, 120, 106, + + 114, 111, 107, 101, 114, 114, 113, 0, 103, 98, + 101, 91, 0, 99, 97, 101, 104, 91, 98, 105, + 102, 96, 90, 0, 86, 83, 83, 0, 77, 91, + 88, 89, 0, 76, 83, 78, 74, 0, 77, 79, + 71, 0, 81, 77, 0, 0, 0, 0, 68, 66, + 70, 72, 64, 76, 67, 0, 70, 0, 0, 69, + 66, 57, 70, 65, 0, 0, 59, 58, 70, 53, + 65, 54, 54, 53, 49, 0, 0, 51, 0, 41, + 0, 0, 0, 208, 70, 83 + } ; + +static yyconst flex_int16_t yy_def[187] = + { 0, + 184, 1, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 185, 184, + 184, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 184, 184, 184, 186, + 184, 184, 184, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 186, 184, 184, 184, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 0, 184, 184 + } ; + +static yyconst flex_uint16_t yy_nxt[256] = + { 0, + 4, 5, 6, 5, 4, 7, 8, 9, 10, 4, + 11, 4, 12, 13, 14, 15, 16, 17, 18, 19, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 19, + 19, 28, 19, 29, 30, 31, 32, 33, 19, 34, + 35, 36, 19, 19, 19, 37, 38, 39, 41, 39, + 42, 48, 51, 55, 62, 49, 60, 43, 67, 61, + 52, 63, 68, 39, 43, 39, 56, 41, 66, 42, + 77, 88, 44, 108, 114, 43, 43, 109, 78, 89, + 183, 115, 43, 43, 65, 65, 182, 181, 180, 179, + 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, + + 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, + 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, + 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, + 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, + 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, + 118, 117, 116, 113, 112, 111, 110, 107, 106, 105, + 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, + 94, 93, 92, 91, 68, 68, 90, 87, 86, 85, + 84, 83, 82, 81, 80, 79, 76, 75, 74, 73, + 72, 71, 70, 69, 66, 64, 59, 58, 57, 54, + + 53, 50, 47, 46, 45, 40, 184, 3, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184 + } ; + +static yyconst flex_int16_t yy_chk[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 5, 13, 5, + 13, 25, 27, 30, 35, 25, 34, 13, 43, 34, + 27, 35, 43, 39, 13, 39, 30, 42, 66, 42, + 53, 63, 185, 87, 92, 66, 42, 87, 53, 63, + 180, 92, 66, 42, 186, 186, 178, 175, 174, 173, + 172, 171, 170, 169, 168, 167, 164, 163, 162, 161, + + 160, 157, 155, 154, 153, 152, 151, 150, 149, 144, + 143, 141, 140, 139, 137, 136, 135, 134, 132, 131, + 130, 129, 127, 126, 125, 123, 122, 121, 120, 119, + 118, 117, 116, 115, 114, 112, 111, 110, 109, 107, + 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, + 95, 94, 93, 91, 90, 89, 88, 86, 85, 84, + 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, + 73, 72, 71, 70, 68, 67, 64, 62, 61, 60, + 59, 58, 57, 56, 55, 54, 52, 51, 50, 49, + 48, 47, 46, 45, 41, 36, 33, 32, 31, 29, + + 28, 26, 24, 23, 22, 12, 3, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "tokens.l" +#line 2 "tokens.l" +//====================================================================================// +// // +// Lexical Analyzer // +// // +//====================================================================================// +// This File: tokens.l Tool: lex // +// Software: SIMULEAU // +// Doc: // +//====================================================================================// +// Creation: 15/Apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 15/Apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +// This file has the definitions of the tokens that must to be recognized by the // +// grammar contained in the "glc.y" file. These definitions are used by LEX tool, // +// which is a generator of lexical parsers. // +// The lexical analyzer (scanner) is a function that reads an input stream and // +// returns the correspondents tokens. // +//====================================================================================// +#include "bpnfile.h" + +extern int yynerrs; // Variable of the YACC generator to count the number of errors. +extern int yylineno; + +//====================================================================================// +// Below are defined the R.E.(Regular Expressions) that defines the format of the // +// digits (symbols between 0 and 9, inclusively), integers, reals, exponents and // +// identifies. The symbol "+" indicate one or more occurrences, the symbol "*" // +// indicate zero or more occurrences and the symbol "?" indicate that the occurrence // +// is optional. // +//====================================================================================// + +#line 613 "lex.yy.cpp" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * _in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * _out_str ); + +yy_size_t yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + +#ifndef YY_NO_UNPUT + + static void yyunput (int c,char *buf_ptr ); + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + { +#line 41 "tokens.l" + + +#line 834 "lex.yy.cpp" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 185 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 208 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 43 "tokens.l" + + YY_BREAK +case 2: +YY_RULE_SETUP +#line 44 "tokens.l" +{return(TK_ARC);} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 45 "tokens.l" +{return(TK_BATCH);} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 46 "tokens.l" +{return(TK_CONTINUOUS);} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 47 "tokens.l" +{return(TK_CONTROLLED);} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 48 "tokens.l" +{return(TK_DESCRIPTION);} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 49 "tokens.l" +{return(TK_DISCRETE);} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 50 "tokens.l" +{return(TK_EVENTS);} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 51 "tokens.l" +{return(TK_FLOW);} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 52 "tokens.l" +{return(TK_FUNCTION);} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 53 "tokens.l" +{return(TK_INITIAL);} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 54 "tokens.l" +{return(TK_INSPECTION);} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 55 "tokens.l" +{return(TK_LENGTH);} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 56 "tokens.l" +{return(TK_MARKING);} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 57 "tokens.l" +{return(TK_MODEL);} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 58 "tokens.l" +{return(TK_NETWORK);} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 59 "tokens.l" +{return(TK_OUTPUT);} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 60 "tokens.l" +{return(TK_PLACE);} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 61 "tokens.l" +{return(TK_PLACES);} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 62 "tokens.l" +{return(TK_SPEED);} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 63 "tokens.l" +{return(TK_STEADY);} + YY_BREAK +case 22: +YY_RULE_SETUP +#line 64 "tokens.l" +{return(TK_TIME);} + YY_BREAK +case 23: +YY_RULE_SETUP +#line 65 "tokens.l" +{return(TK_TIMING);} + YY_BREAK +case 24: +YY_RULE_SETUP +#line 66 "tokens.l" +{return(TK_TRANSITION);} + YY_BREAK +case 25: +YY_RULE_SETUP +#line 67 "tokens.l" +{return(TK_TRANSITIONS);} + YY_BREAK +case 26: +YY_RULE_SETUP +#line 68 "tokens.l" +{return(TK_TRIANGULAR);} + YY_BREAK +case 27: +YY_RULE_SETUP +#line 69 "tokens.l" +{return(TK_UNITY);} + YY_BREAK +case 28: +YY_RULE_SETUP +#line 70 "tokens.l" +{return(TK_ID);} + YY_BREAK +case 29: +YY_RULE_SETUP +#line 71 "tokens.l" +{return(TK_INTEGER);} + YY_BREAK +case 30: +YY_RULE_SETUP +#line 72 "tokens.l" +{return(TK_REAL);} + YY_BREAK +case 31: +YY_RULE_SETUP +#line 73 "tokens.l" +{return(TK_EXPONENT);} + YY_BREAK +case 32: +YY_RULE_SETUP +#line 74 "tokens.l" +{return(TK_AT);} + YY_BREAK +case 33: +YY_RULE_SETUP +#line 75 "tokens.l" +{return(TK_EVERY);} + YY_BREAK +case 34: +YY_RULE_SETUP +#line 76 "tokens.l" +{return(TK_PL_TR);} + YY_BREAK +case 35: +YY_RULE_SETUP +#line 77 "tokens.l" +{return(TK_ALL);} + YY_BREAK +case 36: +YY_RULE_SETUP +#line 78 "tokens.l" +{return(TK_LEFT_BRACKET);} + YY_BREAK +case 37: +YY_RULE_SETUP +#line 79 "tokens.l" +{return(TK_RIGHT_BRACKET);} + YY_BREAK +case 38: +YY_RULE_SETUP +#line 80 "tokens.l" +{return(TK_LEFT_PARENTHESIS);} + YY_BREAK +case 39: +YY_RULE_SETUP +#line 81 "tokens.l" +{return(TK_RIGHT_PARENTHESIS);} + YY_BREAK +case 40: +YY_RULE_SETUP +#line 82 "tokens.l" +{return(TK_LEFT_SQUARE_BRACKET);} + YY_BREAK +case 41: +YY_RULE_SETUP +#line 83 "tokens.l" +{return(TK_RIGHT_SQUARE_BRACKET);} + YY_BREAK +case 42: +YY_RULE_SETUP +#line 84 "tokens.l" +{return(TK_SEMICOLON);} + YY_BREAK +case 43: +YY_RULE_SETUP +#line 85 "tokens.l" +{return(TK_COMMA);} + YY_BREAK +case 44: +YY_RULE_SETUP +#line 86 "tokens.l" +{return(TK_ATTRIB);} + YY_BREAK +case 45: +YY_RULE_SETUP +#line 87 "tokens.l" +{return(TK_COLON);} + YY_BREAK +case 46: +YY_RULE_SETUP +#line 88 "tokens.l" +{/* Ignore the blanks, tabulates and new line */} + YY_BREAK +case 47: +/* rule 47 can match eol */ +YY_RULE_SETUP +#line 89 "tokens.l" +{yylineno++;} + YY_BREAK +case 48: +YY_RULE_SETUP +#line 90 "tokens.l" +{ /* If neither token return, means that the input + stream has a lexical error */ + yynerrs++; + Lexical_Error(yynerrs, yylineno, yytext);} + YY_BREAK +case 49: +YY_RULE_SETUP +#line 94 "tokens.l" +ECHO; + YY_BREAK +#line 1140 "lex.yy.cpp" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + yy_size_t number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 185 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 185 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 184); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + + static void yyunput (int c, char * yy_bp ) +{ + char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + yy_size_t number_to_move = (yy_n_chars) + 2; + char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = (yy_size_t)size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + yy_size_t i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +yy_size_t yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param _line_number line number + * + */ +void yyset_lineno (int _line_number ) +{ + + yylineno = _line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str ) +{ + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str ) +{ + yyout = _out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int _bdebug ) +{ + yy_flex_debug = _bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 94 "tokens.l" + + + +int yywrap () +{ + return(1); +} + +void go2init() +{ + yy_init = 1; +} + diff --git a/src/interf/prf.cpp b/src/interf/prf.cpp new file mode 100644 index 0000000..0ec7362 --- /dev/null +++ b/src/interf/prf.cpp @@ -0,0 +1,209 @@ +//====================================================================================// +// // +// Preferences Structure // +// // +//====================================================================================// +// This File: prf.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +// Error Codes: 6100 // +//====================================================================================// +// Creation: 12/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 12/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + + //--------------------------------------------------------------------------// + // Constructor // + //--------------------------------------------------------------------------// +PRF::PRF() +{ + strcpy(file_name, "defaults"); + Defaults(); +} + //--------------------------------------------------------------------------// + // Destructor // + //--------------------------------------------------------------------------// +PRF::~PRF() +{ +} + //--------------------------------------------------------------------------// + // It puts the defaults values // + //--------------------------------------------------------------------------// +void PRF::Defaults() +{ + verbose = def_verbose; + max_time = def_time; + min_error = def_err; + thresh = def_thresh; + strcpy(length_unity, def_length_unity); + strcpy(time_unity, def_time_unity); +} + //--------------------------------------------------------------------------// + // It returns the file name // + //--------------------------------------------------------------------------// +char* PRF::Name() +{ + return(file_name); +} + + //--------------------------------------------------------------------------// + // It assigns a file name // + //--------------------------------------------------------------------------// +void PRF::Baptise(const simuleau_name file) +{ + strcpy(file_name, file); +} + + //--------------------------------------------------------------------------// + // It returns the current verbose mode // + //--------------------------------------------------------------------------// +int PRF::Verb() const +{ + return(verbose); +} + //--------------------------------------------------------------------------// + // It sets the verbose mode to 'm' // + //--------------------------------------------------------------------------// +void PRF::Verb(const int m) +{ + verbose = m; +} + //--------------------------------------------------------------------------// + // It returns the current verbose mode // + //--------------------------------------------------------------------------// +char* PRF::Sverb() +{ + switch (verbose) { + case 0 : return("level 0"); + case 1 : return("level 1"); + case 2 : return("level 1"); + default : Programming_Error("preference options must be updated", 6101) + } +} + //--------------------------------------------------------------------------// + // It returns the current maximum simulation time // + //--------------------------------------------------------------------------// +double PRF::Max_Time() const +{ + return(max_time); +} + //--------------------------------------------------------------------------// + // It sets the maximum simulation time to 't' // + //--------------------------------------------------------------------------// +void PRF::Max_Time(const double t) +{ + max_time = t; +} + //--------------------------------------------------------------------------// + // It returns the current minimum error // + //--------------------------------------------------------------------------// +double PRF::Min_Err() const +{ + return(min_error); +} + + //--------------------------------------------------------------------------// + // It returns the current minimum error for date computation // + //--------------------------------------------------------------------------// +double PRF::Min_Err_Date() const +{ + return(min_error/1000); +} + + //--------------------------------------------------------------------------// + // It sets the minimum error to 'e' // + //--------------------------------------------------------------------------// +void PRF::Min_Err(const double e) +{ + min_error = e; +} + //--------------------------------------------------------------------------// + // It returns the current threshold // + //--------------------------------------------------------------------------// +double PRF::Thrs() const +{ + return(thresh); +} + //--------------------------------------------------------------------------// + // It sets the threshold to 't' // + //--------------------------------------------------------------------------// +void PRF::Thrs(const double t) +{ + thresh = t; +} + + //--------------------------------------------------------------------------// + // It returns the current length unity // + //--------------------------------------------------------------------------// +char* PRF::Length_Unity() +{ + return(length_unity); +} + //--------------------------------------------------------------------------// + // It sets the length unity to 'lu' // + //--------------------------------------------------------------------------// +void PRF::Length_Unity(const simuleau_name lu) +{ + strcpy(length_unity, lu); +} + + //--------------------------------------------------------------------------// + // It returns the current time unity // + //--------------------------------------------------------------------------// +char* PRF::Time_Unity() +{ + return(time_unity); +} + //--------------------------------------------------------------------------// + // It sets the time unity to 'tu' // + //--------------------------------------------------------------------------// +void PRF::Time_Unity(const simuleau_name tu) +{ + strcpy(time_unity, tu); +} + + //--------------------------------------------------------------------------// + // Output on 'fout' file stream // + //--------------------------------------------------------------------------// +void PRF::Write() const +{ + ofstream fout; + + Open_File(file_name, prf_file, fout); + fout << verbose << "\n"; + fout << max_time << "\n"; + fout << min_error << "\n"; + fout << thresh << "\n"; + fout << length_unity << "\n"; + fout << time_unity << "\n"; + Close_File(file_name, prf_file, fout); +} + //--------------------------------------------------------------------------// + // Input from 'fin' file stream // + //--------------------------------------------------------------------------// +void PRF::Read(const simuleau_name file) +{ + ifstream fin; + + Open_File(file, prf_file, fin); + Baptise(file); + fin >> verbose; + fin >> max_time; + fin >> min_error; + fin >> thresh; + fin >> length_unity; + fin >> time_unity; + Close_File(file_name, prf_file, fin); +} + //--------------------------------------------------------------------------// + // Memory space used by 'this' (in memory units) // + //--------------------------------------------------------------------------// +int PRF::Mem_use() const +{ + return(max_simuleau_name+sizeof(bool)+3*sizeof(double)); +} + + //--------------------------------------------------------------------------// + // static variable: The User Preferences // + //--------------------------------------------------------------------------// +PRF PRF::prf = PRF(); diff --git a/src/interf/prf.h b/src/interf/prf.h new file mode 100644 index 0000000..8d3c21c --- /dev/null +++ b/src/interf/prf.h @@ -0,0 +1,69 @@ +//====================================================================================// +// // +// Preferences Structure // +// // +//====================================================================================// +// This File: prf.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +// Error Codes: 6100 // +//====================================================================================// +// Creation: 12/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 12/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +// This class is used to store the static variable 'PRF::prf' which contains most // +// of the user choices in Simuleau. // +//====================================================================================// +#ifndef PRF_H +#define PRF_H + +class PRF +{ +public: + PRF(); // Constructor + ~PRF(); // Destructor + void Defaults(); // It puts the defaults values + + char* Name(); // It returns the file name + void Baptise(const simuleau_name file); // It assigns a file name + + int Verb() const; // It returns the current verbose mode + void Verb(const int m); // It sets the verbose mode to 'm' + char* Sverb(); // string answer + + double Max_Time() const; // It returns the current maximum simulation time + void Max_Time(const double t); // It sets the maximum simulation time to 't' + + double Min_Err() const; // It returns the current minimum error + double Min_Err_Date() const; // It returns the current minimum error + void Min_Err(const double e); // It sets the minimum error to 'e' + + double Thrs() const; // It returns the current threshold + void Thrs(const double t); // It sets the threshold to 't' + + char* Length_Unity(); // It returns the current lenght unity + void Length_Unity(const simuleau_name lu); //It sets the lenght unity to 'lu' + + char* Time_Unity(); // It returns the current time unity + void Time_Unity(const simuleau_name tu); //It sets the time unity to 'tu' + + void Write() const; // Output on 'fout' file stream + void Read(const simuleau_name file); // Input from 'fin' file stream + int Mem_use() const; // Memory space used by 'this' (in bytes) + + //--------------------------------------------------------------------------// + // Static variable // + //--------------------------------------------------------------------------// + static PRF prf; + + //--------------------------------------------------------------------------// + // Data Structures // + //--------------------------------------------------------------------------// +private: simuleau_name file_name; // the file name of this structure + int verbose; // Verbose mode + double max_time; // Maximum simulation time + double min_error; // Minimum error + double thresh; // Threshold + simuleau_name length_unity; // Length unity + simuleau_name time_unity; // Time unity +}; +#endif // PRF_H diff --git a/src/interf/test b/src/interf/test new file mode 100644 index 0000000..2abb954 --- /dev/null +++ b/src/interf/test @@ -0,0 +1,54 @@ +// comments + +model test; +length unity= km ; +time unity = h; + +network description +places + place P1 (discrete) + initial marking {1} + output arc T1 + output arc T2 (2) + + place p2 (continuous) + initial marking {2.5} + output arc T3 (1) + output arc t4 + + place pl (batch) + function (10,120, 200 ) + initial marking { (1, 1.2, 100) } +// output arc t5 +// output arc t6 (3) + + place pt (triangular) + function ( 120, 250, 10.4, 4000) + initial marking { (2.3, 1.0,50, 200) , + (3, 10, 120, 300) } + output arc t6 (3.2) + +transitions + transition T1 (discrete) + timing (5.1) + output arc P1 + output arc p2 (2) + + transition T2 (continuous) + flow (300.5) + output arc p2 + output arc pl + + transition t3 (batch) + flow (4000) + output arc pt + +controlled events // les evenements controlles pourrons aussi etre lu a partir d un fichier externe + ev1 = (flow, p1, 4000, 0.001); + ev2 = (speed, pt, 120, 0.002); + +time inspection // affiche l information d une place(caracteristiques+lots)/transition(flux) a l instant <time> + res1 = @ 1.001 ? pt; + res2 = # 1.02 * places + + diff --git a/src/interf/timer.cpp b/src/interf/timer.cpp new file mode 100644 index 0000000..0753f96 --- /dev/null +++ b/src/interf/timer.cpp @@ -0,0 +1,103 @@ +// ======================================================================= // +// Class Timer : +// (c) copyright PAC++ 1994 +// date: 1994 +// ======================================================================= // + +#include <math.h> +extern "C" { +#include <sys/time.h> +#include <sys/resource.h> + // int getrusage (int, struct rusage*) ; *** removed for g++ compiler +} +#include <iostream> + +using namespace std; + +#include "timer.h" + + // Clear timer : +void Timer::clear() { ut = st = rt = 0 ; } + + // Start timer +void Timer::start() +{ + struct rusage tmp1 ; // to getrusage (sys+user times) + struct timeval tmp2 ; // to gettimeofday (real time) + getrusage (RUSAGE_SELF, &tmp1) ; + gettimeofday (&tmp2, 0) ; + + // user time + ut = (double) tmp1.ru_utime.tv_sec + + ((double) tmp1.ru_utime.tv_usec)/ (double)MSPSEC ; + // system time + st = (double) tmp1.ru_stime.tv_sec + + ((double) tmp1.ru_stime.tv_usec)/ (double)MSPSEC ; + // real time + rt = (double) tmp2.tv_sec + + ((double) tmp2.tv_usec)/ (double)MSPSEC ; +} + + // Stop timer +void Timer::stop() +{ + double uts = ut, sts = st , rts = rt ; + start() ; + ut -= uts ; st -= sts ; rt -= rts ; +} + + // Return a value to initialize random generator +long Timer::seed() +{ + struct timeval tp; + gettimeofday(&tp, 0) ; + return(tp.tv_usec); + return 1 ; +} + + // Output the value of the timer : +ostream& operator<<(ostream& o, const Timer& T) +{ + o << "user time: " << T.usertime() << '\n' ; + o << "sys. time: " << T.systime() << '\n' ; + o << "real time: " << T.realtime() << endl ; + return o ; +} + + // Some arithmetic operator : +Timer& Timer::operator = (const Timer & T) +{ + ut = T.ut ; st = T.st ; rt = T.rt ; + return *this ; +} + + // Computes and returns interval of time + // beteween *this and T +const Timer Timer::operator - (const Timer & T) const +{ + Timer Tmp ; + Tmp.ut = ut - T.ut ; + Tmp.st = st - T.st ; + Tmp.rt = rt - T.rt ; + return Tmp ; +} + +const Timer Timer::operator - () +{ + Timer Tmp ; + Tmp.ut = -ut ; + Tmp.st = -st ; + Tmp.rt = -rt ; + return Tmp ; +} + +const Timer Timer::operator + (const Timer & T) const +{ + Timer Tmp ; + Tmp.ut = ut + T.ut ; + Tmp.st = st + T.st ; + Tmp.rt = rt + T.rt ; + return Tmp ; +} + + diff --git a/src/interf/timer.h b/src/interf/timer.h new file mode 100644 index 0000000..48805fd --- /dev/null +++ b/src/interf/timer.h @@ -0,0 +1,56 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ +// ======================================================================= // +// Class Timer : +// (c) copyright PAC++ 1994 +// date: 1994 +// ======================================================================= // + +class Timer { +enum { + MSPSEC = 1000000 // microsecond per second +} ; +public : + + // Clear timer : + void clear() ; + + // Start timer + void start() ; + + // Stop timer + void stop() ; + + // total amount of second spent in user mode + double usertime() const { return ut ; } + + // total amount of second spent in system mode + double systime () const { return st ; } + + // real total amount of second spent. + double realtime () const { return rt ; } + + // retourne une petite graine + long seed() ; + + // Output the value of the timer : + friend ostream& operator<<(ostream& o, const Timer& T) ; + + // Some arithmetic operators to compute cumulative time : + Timer& operator = (const Timer & T) ; + const Timer operator - (const Timer & T) const ; + const Timer operator - () ; + const Timer operator + (const Timer & T) const ; + const Timer operator += (const Timer & T) { return *this = *this + T; } ; + const Timer operator -= (const Timer & T) { return *this = *this - T; } ; + + +private : + double ut ; // user time + double st ; // system time + double rt ; // real time +} ; + + + +#endif diff --git a/src/interf/tokens.l b/src/interf/tokens.l new file mode 100644 index 0000000..7b0ccbe --- /dev/null +++ b/src/interf/tokens.l @@ -0,0 +1,104 @@ +%{ +//====================================================================================// +// // +// Lexical Analyzer // +// // +//====================================================================================// +// This File: tokens.l Tool: lex // +// Software: SIMULEAU // +// Doc: // +//====================================================================================// +// Creation: 15/Apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 15/Apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +// This file has the definitions of the tokens that must to be recognized by the // +// grammar contained in the "glc.y" file. These definitions are used by LEX tool, // +// which is a generator of lexical parsers. // +// The lexical analyzer (scanner) is a function that reads an input stream and // +// returns the correspondents tokens. // +//====================================================================================// +#include "bpnfile.h" + +extern int yynerrs; // Variable of the YACC generator to count the number of errors. +extern int yylineno; + +//====================================================================================// +// Below are defined the R.E.(Regular Expressions) that defines the format of the // +// digits (symbols between 0 and 9, inclusively), integers, reals, exponents and // +// identifies. The symbol "+" indicate one or more occurrences, the symbol "*" // +// indicate zero or more occurrences and the symbol "?" indicate that the occurrence // +// is optional. // +//====================================================================================// + +%} + +digit [0-9] +integer {digit}+ +real {integer}"."{integer} +exponent ({integer}|{real})[Ee][+-]?{integer} +id [A-Za-z_][A-Za-z0-9_]* + +%% + +"//"[0-9A-Za-z\'\-\!\"\#\$\%\&\(\)\*\+\,\-\.\/:\;\<\>\=\?\@\\\]\[\}\{\^\_\~\| ]* +"arc" {return(TK_ARC);} +"batch" {return(TK_BATCH);} +"continuous" {return(TK_CONTINUOUS);} +"controlled" {return(TK_CONTROLLED);} +"description" {return(TK_DESCRIPTION);} +"discrete" {return(TK_DISCRETE);} +"events" {return(TK_EVENTS);} +"flow" {return(TK_FLOW);} +"function" {return(TK_FUNCTION);} +"initial" {return(TK_INITIAL);} +"inspection" {return(TK_INSPECTION);} +"length" {return(TK_LENGTH);} +"marking" {return(TK_MARKING);} +"model" {return(TK_MODEL);} +"network" {return(TK_NETWORK);} +"output" {return(TK_OUTPUT);} +"place" {return(TK_PLACE);} +"places" {return(TK_PLACES);} +"speed" {return(TK_SPEED);} +"steady" {return(TK_STEADY);} +"time" {return(TK_TIME);} +"timing" {return(TK_TIMING);} +"transition" {return(TK_TRANSITION);} +"transitions" {return(TK_TRANSITIONS);} +"triangular" {return(TK_TRIANGULAR);} +"unity" {return(TK_UNITY);} +{id} {return(TK_ID);} +{integer} {return(TK_INTEGER);} +{real} {return(TK_REAL);} +{exponent} {return(TK_EXPONENT);} +"@" {return(TK_AT);} +"#" {return(TK_EVERY);} +"?" {return(TK_PL_TR);} +"*" {return(TK_ALL);} +"{" {return(TK_LEFT_BRACKET);} +"}" {return(TK_RIGHT_BRACKET);} +"(" {return(TK_LEFT_PARENTHESIS);} +")" {return(TK_RIGHT_PARENTHESIS);} +"[" {return(TK_LEFT_SQUARE_BRACKET);} +"]" {return(TK_RIGHT_SQUARE_BRACKET);} +";" {return(TK_SEMICOLON);} +"," {return(TK_COMMA);} +"=" {return(TK_ATTRIB);} +":" {return(TK_COLON);} +[ \t]* {/* Ignore the blanks, tabulates and new line */} +[\n] {yylineno++;} +. { /* If neither token return, means that the input + stream has a lexical error */ + yynerrs++; + Lexical_Error(yynerrs, yylineno, yytext);} +%% + +int yywrap () +{ + return(1); +} + +void go2init() +{ + yy_init = 1; +} diff --git a/src/interf/y.output b/src/interf/y.output new file mode 100644 index 0000000..f54a138 --- /dev/null +++ b/src/interf/y.output @@ -0,0 +1,2550 @@ +Terminals unused in grammar + + TK_LEFT_SQUARE_BRACKET + TK_RIGHT_SQUARE_BRACKET + TK_COLON + + +Grammar + + 0 $accept: start $end + + 1 start: blk_def blk_net blk_controlled_events blk_time_inspection + + 2 blk_def: blk_model blk_unity + + 3 $@1: %empty + + 4 blk_model: TK_MODEL TK_ID $@1 semi_colon + 5 | %empty + + 6 blk_unity: blk_lenght blk_time + + 7 $@2: %empty + + 8 blk_lenght: TK_LENGTH TK_UNITY TK_ATTRIB TK_ID $@2 semi_colon + 9 | %empty + + 10 $@3: %empty + + 11 blk_time: TK_TIME TK_UNITY TK_ATTRIB TK_ID $@3 semi_colon + 12 | %empty + + 13 semi_colon: TK_SEMICOLON + 14 | %empty + + 15 number: TK_REAL + 16 | TK_INTEGER + 17 | TK_EXPONENT + + 18 blk_net: TK_NETWORK TK_DESCRIPTION blk_places blk_transitions + + 19 $@4: %empty + + 20 blk_places: TK_PLACES $@4 blk_place + + 21 $@5: %empty + + 22 blk_transitions: TK_TRANSITIONS $@5 blk_transition + + 23 $@6: %empty + + 24 $@7: %empty + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + + 26 blk_place2: blk_place + 27 | %empty + + 28 blk_place_type: TK_DISCRETE + 29 | TK_CONTINUOUS + 30 | TK_BATCH + 31 | TK_TRIANGULAR + + 32 $@8: %empty + + 33 $@9: %empty + + 34 $@10: %empty + + 35 $@11: %empty + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA number $@10 TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + 37 | %empty + + 38 blk_triangular_place: TK_COMMA number + 39 | %empty + + 40 blk_initial_marking: TK_INITIAL TK_MARKING TK_LEFT_BRACKET blk_initial_marking_int TK_RIGHT_BRACKET + + 41 blk_initial_marking_int: number + 42 | blk_batch + + 43 $@12: %empty + + 44 $@13: %empty + + 45 $@14: %empty + + 46 $@15: %empty + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number $@13 TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + 48 | %empty + + 49 blk_batch2: TK_COMMA blk_batch + 50 | %empty + + 51 blk_triangular_batch: TK_COMMA number + 52 | %empty + + 53 blk_steady_marking: TK_STEADY TK_MARKING TK_LEFT_BRACKET blk_steady_marking_int TK_RIGHT_BRACKET + 54 | %empty + + 55 blk_steady_marking_int: number + 56 | blk_steady_batch + + 57 $@16: %empty + + 58 $@17: %empty + + 59 $@18: %empty + + 60 $@19: %empty + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number $@17 TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + 62 | %empty + + 63 blk_steady_batch2: TK_COMMA blk_steady_batch + 64 | %empty + + 65 blk_steady_triangular_batch: TK_COMMA number + 66 | %empty + + 67 $@20: %empty + + 68 $@21: %empty + + 69 blk_place_arcs: TK_OUTPUT TK_ARC TK_ID $@20 blk_place_weight $@21 blk_place_arcs2 + 70 | %empty + + 71 blk_place_arcs2: blk_place_arcs + + 72 $@22: %empty + + 73 blk_place_weight: TK_LEFT_PARENTHESIS number $@22 TK_RIGHT_PARENTHESIS + 74 | %empty + + 75 $@23: %empty + + 76 $@24: %empty + + 77 $@25: %empty + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 + + 79 blk_transition2: blk_transition + 80 | %empty + + 81 blk_transition_type: TK_DISCRETE + 82 | TK_CONTINUOUS + 83 | TK_BATCH + + 84 $@26: %empty + + 85 blk_transition_function: TK_TIMING TK_LEFT_PARENTHESIS number $@26 TK_RIGHT_PARENTHESIS + + 86 $@27: %empty + + 87 blk_transition_function: TK_FLOW TK_LEFT_PARENTHESIS number $@27 TK_RIGHT_PARENTHESIS + + 88 blk_steady_transition_function: TK_STEADY blk_steady_transition_function_int + 89 | %empty + + 90 $@28: %empty + + 91 blk_steady_transition_function_int: TK_TIMING TK_LEFT_PARENTHESIS number $@28 TK_RIGHT_PARENTHESIS + + 92 $@29: %empty + + 93 blk_steady_transition_function_int: TK_FLOW TK_LEFT_PARENTHESIS number $@29 TK_RIGHT_PARENTHESIS + + 94 $@30: %empty + + 95 $@31: %empty + + 96 blk_transition_arcs: TK_OUTPUT TK_ARC TK_ID $@30 blk_transition_weight $@31 blk_transition_arcs2 + 97 | %empty + + 98 blk_transition_arcs2: blk_transition_arcs + + 99 $@32: %empty + + 100 blk_transition_weight: TK_LEFT_PARENTHESIS number $@32 TK_RIGHT_PARENTHESIS + 101 | %empty + + 102 $@33: %empty + + 103 blk_controlled_events: TK_CONTROLLED TK_EVENTS $@33 controlled_events + 104 | %empty + + 105 $@34: %empty + + 106 $@35: %empty + + 107 $@36: %empty + + 108 $@37: %empty + + 109 $@38: %empty + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + 111 | %empty + + 112 controlled_events2: controlled_events + + 113 controlled_events_type: TK_FLOW + 114 | TK_SPEED + + 115 $@39: %empty + + 116 blk_time_inspection: TK_TIME TK_INSPECTION $@39 time_inspection + 117 | %empty + + 118 $@40: %empty + + 119 $@41: %empty + + 120 $@42: %empty + + 121 $@43: %empty + + 122 time_inspection: TK_ID $@40 TK_ATTRIB blk_op_time number $@41 blk_op_pt $@42 semi_colon $@43 time_inspection2 + 123 | %empty + + 124 time_inspection2: time_inspection + + 125 blk_op_time: TK_AT + 126 | TK_EVERY + + 127 blk_op_pt: TK_PL_TR TK_ID + 128 | TK_ALL blk_pl_tr + + 129 blk_pl_tr: TK_PLACES + 130 | TK_TRANSITIONS + + +Terminals, with rules where they appear + + $end (0) 0 + error (256) + TK_ARC (258) 69 96 + TK_BATCH (259) 30 83 + TK_CONTINUOUS (260) 29 82 + TK_CONTROLLED (261) 103 + TK_DESCRIPTION (262) 18 + TK_DISCRETE (263) 28 81 + TK_EVENTS (264) 103 + TK_FLOW (265) 87 93 113 + TK_FUNCTION (266) 36 + TK_INITIAL (267) 40 + TK_INSPECTION (268) 116 + TK_LENGTH (269) 8 + TK_MARKING (270) 40 53 + TK_MODEL (271) 4 + TK_NETWORK (272) 18 + TK_OUTPUT (273) 69 96 + TK_PLACE (274) 25 + TK_PLACES (275) 20 129 + TK_SPEED (276) 114 + TK_STEADY (277) 53 88 + TK_TIME (278) 11 116 + TK_TIMING (279) 85 91 + TK_TRANSITION (280) 78 + TK_TRANSITIONS (281) 22 130 + TK_TRIANGULAR (282) 31 + TK_UNITY (283) 8 11 + TK_ID (284) 4 8 11 25 69 78 96 110 122 127 + TK_INTEGER (285) 16 + TK_REAL (286) 15 + TK_EXPONENT (287) 17 + TK_AT (288) 125 + TK_EVERY (289) 126 + TK_LEFT_BRACKET (290) 40 53 + TK_RIGHT_BRACKET (291) 40 53 + TK_PL_TR (292) 127 + TK_ALL (293) 128 + TK_LEFT_PARENTHESIS (294) 25 36 47 61 73 78 85 87 91 93 100 110 + TK_RIGHT_PARENTHESIS (295) 25 36 47 61 73 78 85 87 91 93 100 110 + TK_LEFT_SQUARE_BRACKET (296) + TK_RIGHT_SQUARE_BRACKET (297) + TK_SEMICOLON (298) 13 + TK_COMMA (299) 36 38 47 49 51 61 63 65 110 + TK_ATTRIB (300) 8 11 110 122 + TK_COLON (301) + + +Nonterminals, with rules where they appear + + $accept (47) + on left: 0 + start (48) + on left: 1 + on right: 0 + blk_def (49) + on left: 2 + on right: 1 + blk_model (50) + on left: 4 5 + on right: 2 + $@1 (51) + on left: 3 + on right: 4 + blk_unity (52) + on left: 6 + on right: 2 + blk_lenght (53) + on left: 8 9 + on right: 6 + $@2 (54) + on left: 7 + on right: 8 + blk_time (55) + on left: 11 12 + on right: 6 + $@3 (56) + on left: 10 + on right: 11 + semi_colon (57) + on left: 13 14 + on right: 4 8 11 110 122 + number (58) + on left: 15 16 17 + on right: 36 38 41 47 51 55 61 65 73 85 87 91 93 100 110 122 + blk_net (59) + on left: 18 + on right: 1 + blk_places (60) + on left: 20 + on right: 18 + $@4 (61) + on left: 19 + on right: 20 + blk_transitions (62) + on left: 22 + on right: 18 + $@5 (63) + on left: 21 + on right: 22 + blk_place (64) + on left: 25 + on right: 20 26 + $@6 (65) + on left: 23 + on right: 25 + $@7 (66) + on left: 24 + on right: 25 + blk_place2 (67) + on left: 26 27 + on right: 25 + blk_place_type (68) + on left: 28 29 30 31 + on right: 25 + blk_function (69) + on left: 36 37 + on right: 25 + $@8 (70) + on left: 32 + on right: 36 + $@9 (71) + on left: 33 + on right: 36 + $@10 (72) + on left: 34 + on right: 36 + $@11 (73) + on left: 35 + on right: 36 + blk_triangular_place (74) + on left: 38 39 + on right: 36 + blk_initial_marking (75) + on left: 40 + on right: 25 + blk_initial_marking_int (76) + on left: 41 42 + on right: 40 + blk_batch (77) + on left: 47 48 + on right: 42 49 + $@12 (78) + on left: 43 + on right: 47 + $@13 (79) + on left: 44 + on right: 47 + $@14 (80) + on left: 45 + on right: 47 + $@15 (81) + on left: 46 + on right: 47 + blk_batch2 (82) + on left: 49 50 + on right: 47 + blk_triangular_batch (83) + on left: 51 52 + on right: 47 + blk_steady_marking (84) + on left: 53 54 + on right: 25 + blk_steady_marking_int (85) + on left: 55 56 + on right: 53 + blk_steady_batch (86) + on left: 61 62 + on right: 56 63 + $@16 (87) + on left: 57 + on right: 61 + $@17 (88) + on left: 58 + on right: 61 + $@18 (89) + on left: 59 + on right: 61 + $@19 (90) + on left: 60 + on right: 61 + blk_steady_batch2 (91) + on left: 63 64 + on right: 61 + blk_steady_triangular_batch (92) + on left: 65 66 + on right: 61 + blk_place_arcs (93) + on left: 69 70 + on right: 25 71 + $@20 (94) + on left: 67 + on right: 69 + $@21 (95) + on left: 68 + on right: 69 + blk_place_arcs2 (96) + on left: 71 + on right: 69 + blk_place_weight (97) + on left: 73 74 + on right: 69 + $@22 (98) + on left: 72 + on right: 73 + blk_transition (99) + on left: 78 + on right: 22 79 + $@23 (100) + on left: 75 + on right: 78 + $@24 (101) + on left: 76 + on right: 78 + $@25 (102) + on left: 77 + on right: 78 + blk_transition2 (103) + on left: 79 80 + on right: 78 + blk_transition_type (104) + on left: 81 82 83 + on right: 78 + blk_transition_function (105) + on left: 85 87 + on right: 78 + $@26 (106) + on left: 84 + on right: 85 + $@27 (107) + on left: 86 + on right: 87 + blk_steady_transition_function (108) + on left: 88 89 + on right: 78 + blk_steady_transition_function_int (109) + on left: 91 93 + on right: 88 + $@28 (110) + on left: 90 + on right: 91 + $@29 (111) + on left: 92 + on right: 93 + blk_transition_arcs (112) + on left: 96 97 + on right: 78 98 + $@30 (113) + on left: 94 + on right: 96 + $@31 (114) + on left: 95 + on right: 96 + blk_transition_arcs2 (115) + on left: 98 + on right: 96 + blk_transition_weight (116) + on left: 100 101 + on right: 96 + $@32 (117) + on left: 99 + on right: 100 + blk_controlled_events (118) + on left: 103 104 + on right: 1 + $@33 (119) + on left: 102 + on right: 103 + controlled_events (120) + on left: 110 111 + on right: 103 112 + $@34 (121) + on left: 105 + on right: 110 + $@35 (122) + on left: 106 + on right: 110 + $@36 (123) + on left: 107 + on right: 110 + $@37 (124) + on left: 108 + on right: 110 + $@38 (125) + on left: 109 + on right: 110 + controlled_events2 (126) + on left: 112 + on right: 110 + controlled_events_type (127) + on left: 113 114 + on right: 110 + blk_time_inspection (128) + on left: 116 117 + on right: 1 + $@39 (129) + on left: 115 + on right: 116 + time_inspection (130) + on left: 122 123 + on right: 116 124 + $@40 (131) + on left: 118 + on right: 122 + $@41 (132) + on left: 119 + on right: 122 + $@42 (133) + on left: 120 + on right: 122 + $@43 (134) + on left: 121 + on right: 122 + time_inspection2 (135) + on left: 124 + on right: 122 + blk_op_time (136) + on left: 125 126 + on right: 122 + blk_op_pt (137) + on left: 127 128 + on right: 122 + blk_pl_tr (138) + on left: 129 130 + on right: 128 + + +State 0 + + 0 $accept: . start $end + + TK_MODEL shift, and go to state 1 + + $default reduce using rule 5 (blk_model) + + start go to state 2 + blk_def go to state 3 + blk_model go to state 4 + + +State 1 + + 4 blk_model: TK_MODEL . TK_ID $@1 semi_colon + + TK_ID shift, and go to state 5 + + +State 2 + + 0 $accept: start . $end + + $end shift, and go to state 6 + + +State 3 + + 1 start: blk_def . blk_net blk_controlled_events blk_time_inspection + + TK_NETWORK shift, and go to state 7 + + blk_net go to state 8 + + +State 4 + + 2 blk_def: blk_model . blk_unity + + TK_LENGTH shift, and go to state 9 + + $default reduce using rule 9 (blk_lenght) + + blk_unity go to state 10 + blk_lenght go to state 11 + + +State 5 + + 4 blk_model: TK_MODEL TK_ID . $@1 semi_colon + + $default reduce using rule 3 ($@1) + + $@1 go to state 12 + + +State 6 + + 0 $accept: start $end . + + $default accept + + +State 7 + + 18 blk_net: TK_NETWORK . TK_DESCRIPTION blk_places blk_transitions + + TK_DESCRIPTION shift, and go to state 13 + + +State 8 + + 1 start: blk_def blk_net . blk_controlled_events blk_time_inspection + + TK_CONTROLLED shift, and go to state 14 + + $default reduce using rule 104 (blk_controlled_events) + + blk_controlled_events go to state 15 + + +State 9 + + 8 blk_lenght: TK_LENGTH . TK_UNITY TK_ATTRIB TK_ID $@2 semi_colon + + TK_UNITY shift, and go to state 16 + + +State 10 + + 2 blk_def: blk_model blk_unity . + + $default reduce using rule 2 (blk_def) + + +State 11 + + 6 blk_unity: blk_lenght . blk_time + + TK_TIME shift, and go to state 17 + + $default reduce using rule 12 (blk_time) + + blk_time go to state 18 + + +State 12 + + 4 blk_model: TK_MODEL TK_ID $@1 . semi_colon + + TK_SEMICOLON shift, and go to state 19 + + $default reduce using rule 14 (semi_colon) + + semi_colon go to state 20 + + +State 13 + + 18 blk_net: TK_NETWORK TK_DESCRIPTION . blk_places blk_transitions + + TK_PLACES shift, and go to state 21 + + blk_places go to state 22 + + +State 14 + + 103 blk_controlled_events: TK_CONTROLLED . TK_EVENTS $@33 controlled_events + + TK_EVENTS shift, and go to state 23 + + +State 15 + + 1 start: blk_def blk_net blk_controlled_events . blk_time_inspection + + TK_TIME shift, and go to state 24 + + $default reduce using rule 117 (blk_time_inspection) + + blk_time_inspection go to state 25 + + +State 16 + + 8 blk_lenght: TK_LENGTH TK_UNITY . TK_ATTRIB TK_ID $@2 semi_colon + + TK_ATTRIB shift, and go to state 26 + + +State 17 + + 11 blk_time: TK_TIME . TK_UNITY TK_ATTRIB TK_ID $@3 semi_colon + + TK_UNITY shift, and go to state 27 + + +State 18 + + 6 blk_unity: blk_lenght blk_time . + + $default reduce using rule 6 (blk_unity) + + +State 19 + + 13 semi_colon: TK_SEMICOLON . + + $default reduce using rule 13 (semi_colon) + + +State 20 + + 4 blk_model: TK_MODEL TK_ID $@1 semi_colon . + + $default reduce using rule 4 (blk_model) + + +State 21 + + 20 blk_places: TK_PLACES . $@4 blk_place + + $default reduce using rule 19 ($@4) + + $@4 go to state 28 + + +State 22 + + 18 blk_net: TK_NETWORK TK_DESCRIPTION blk_places . blk_transitions + + TK_TRANSITIONS shift, and go to state 29 + + blk_transitions go to state 30 + + +State 23 + + 103 blk_controlled_events: TK_CONTROLLED TK_EVENTS . $@33 controlled_events + + $default reduce using rule 102 ($@33) + + $@33 go to state 31 + + +State 24 + + 116 blk_time_inspection: TK_TIME . TK_INSPECTION $@39 time_inspection + + TK_INSPECTION shift, and go to state 32 + + +State 25 + + 1 start: blk_def blk_net blk_controlled_events blk_time_inspection . + + $default reduce using rule 1 (start) + + +State 26 + + 8 blk_lenght: TK_LENGTH TK_UNITY TK_ATTRIB . TK_ID $@2 semi_colon + + TK_ID shift, and go to state 33 + + +State 27 + + 11 blk_time: TK_TIME TK_UNITY . TK_ATTRIB TK_ID $@3 semi_colon + + TK_ATTRIB shift, and go to state 34 + + +State 28 + + 20 blk_places: TK_PLACES $@4 . blk_place + + TK_PLACE shift, and go to state 35 + + blk_place go to state 36 + + +State 29 + + 22 blk_transitions: TK_TRANSITIONS . $@5 blk_transition + + $default reduce using rule 21 ($@5) + + $@5 go to state 37 + + +State 30 + + 18 blk_net: TK_NETWORK TK_DESCRIPTION blk_places blk_transitions . + + $default reduce using rule 18 (blk_net) + + +State 31 + + 103 blk_controlled_events: TK_CONTROLLED TK_EVENTS $@33 . controlled_events + + TK_ID shift, and go to state 38 + + $default reduce using rule 111 (controlled_events) + + controlled_events go to state 39 + + +State 32 + + 116 blk_time_inspection: TK_TIME TK_INSPECTION . $@39 time_inspection + + $default reduce using rule 115 ($@39) + + $@39 go to state 40 + + +State 33 + + 8 blk_lenght: TK_LENGTH TK_UNITY TK_ATTRIB TK_ID . $@2 semi_colon + + $default reduce using rule 7 ($@2) + + $@2 go to state 41 + + +State 34 + + 11 blk_time: TK_TIME TK_UNITY TK_ATTRIB . TK_ID $@3 semi_colon + + TK_ID shift, and go to state 42 + + +State 35 + + 25 blk_place: TK_PLACE . TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + + TK_ID shift, and go to state 43 + + +State 36 + + 20 blk_places: TK_PLACES $@4 blk_place . + + $default reduce using rule 20 (blk_places) + + +State 37 + + 22 blk_transitions: TK_TRANSITIONS $@5 . blk_transition + + TK_TRANSITION shift, and go to state 44 + + blk_transition go to state 45 + + +State 38 + + 110 controlled_events: TK_ID . $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + $default reduce using rule 105 ($@34) + + $@34 go to state 46 + + +State 39 + + 103 blk_controlled_events: TK_CONTROLLED TK_EVENTS $@33 controlled_events . + + $default reduce using rule 103 (blk_controlled_events) + + +State 40 + + 116 blk_time_inspection: TK_TIME TK_INSPECTION $@39 . time_inspection + + TK_ID shift, and go to state 47 + + $default reduce using rule 123 (time_inspection) + + time_inspection go to state 48 + + +State 41 + + 8 blk_lenght: TK_LENGTH TK_UNITY TK_ATTRIB TK_ID $@2 . semi_colon + + TK_SEMICOLON shift, and go to state 19 + + $default reduce using rule 14 (semi_colon) + + semi_colon go to state 49 + + +State 42 + + 11 blk_time: TK_TIME TK_UNITY TK_ATTRIB TK_ID . $@3 semi_colon + + $default reduce using rule 10 ($@3) + + $@3 go to state 50 + + +State 43 + + 25 blk_place: TK_PLACE TK_ID . $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + + $default reduce using rule 23 ($@6) + + $@6 go to state 51 + + +State 44 + + 78 blk_transition: TK_TRANSITION . TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 + + TK_ID shift, and go to state 52 + + +State 45 + + 22 blk_transitions: TK_TRANSITIONS $@5 blk_transition . + + $default reduce using rule 22 (blk_transitions) + + +State 46 + + 110 controlled_events: TK_ID $@34 . TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_ATTRIB shift, and go to state 53 + + +State 47 + + 122 time_inspection: TK_ID . $@40 TK_ATTRIB blk_op_time number $@41 blk_op_pt $@42 semi_colon $@43 time_inspection2 + + $default reduce using rule 118 ($@40) + + $@40 go to state 54 + + +State 48 + + 116 blk_time_inspection: TK_TIME TK_INSPECTION $@39 time_inspection . + + $default reduce using rule 116 (blk_time_inspection) + + +State 49 + + 8 blk_lenght: TK_LENGTH TK_UNITY TK_ATTRIB TK_ID $@2 semi_colon . + + $default reduce using rule 8 (blk_lenght) + + +State 50 + + 11 blk_time: TK_TIME TK_UNITY TK_ATTRIB TK_ID $@3 . semi_colon + + TK_SEMICOLON shift, and go to state 19 + + $default reduce using rule 14 (semi_colon) + + semi_colon go to state 55 + + +State 51 + + 25 blk_place: TK_PLACE TK_ID $@6 . TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + + TK_LEFT_PARENTHESIS shift, and go to state 56 + + +State 52 + + 78 blk_transition: TK_TRANSITION TK_ID . $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 + + $default reduce using rule 75 ($@23) + + $@23 go to state 57 + + +State 53 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB . TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_LEFT_PARENTHESIS shift, and go to state 58 + + +State 54 + + 122 time_inspection: TK_ID $@40 . TK_ATTRIB blk_op_time number $@41 blk_op_pt $@42 semi_colon $@43 time_inspection2 + + TK_ATTRIB shift, and go to state 59 + + +State 55 + + 11 blk_time: TK_TIME TK_UNITY TK_ATTRIB TK_ID $@3 semi_colon . + + $default reduce using rule 11 (blk_time) + + +State 56 + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS . blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + + TK_BATCH shift, and go to state 60 + TK_CONTINUOUS shift, and go to state 61 + TK_DISCRETE shift, and go to state 62 + TK_TRIANGULAR shift, and go to state 63 + + blk_place_type go to state 64 + + +State 57 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 . TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 + + TK_LEFT_PARENTHESIS shift, and go to state 65 + + +State 58 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS . controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_FLOW shift, and go to state 66 + TK_SPEED shift, and go to state 67 + + controlled_events_type go to state 68 + + +State 59 + + 122 time_inspection: TK_ID $@40 TK_ATTRIB . blk_op_time number $@41 blk_op_pt $@42 semi_colon $@43 time_inspection2 + + TK_AT shift, and go to state 69 + TK_EVERY shift, and go to state 70 + + blk_op_time go to state 71 + + +State 60 + + 30 blk_place_type: TK_BATCH . + + $default reduce using rule 30 (blk_place_type) + + +State 61 + + 29 blk_place_type: TK_CONTINUOUS . + + $default reduce using rule 29 (blk_place_type) + + +State 62 + + 28 blk_place_type: TK_DISCRETE . + + $default reduce using rule 28 (blk_place_type) + + +State 63 + + 31 blk_place_type: TK_TRIANGULAR . + + $default reduce using rule 31 (blk_place_type) + + +State 64 + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type . TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + + TK_RIGHT_PARENTHESIS shift, and go to state 72 + + +State 65 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS . blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 + + TK_BATCH shift, and go to state 73 + TK_CONTINUOUS shift, and go to state 74 + TK_DISCRETE shift, and go to state 75 + + blk_transition_type go to state 76 + + +State 66 + + 113 controlled_events_type: TK_FLOW . + + $default reduce using rule 113 (controlled_events_type) + + +State 67 + + 114 controlled_events_type: TK_SPEED . + + $default reduce using rule 114 (controlled_events_type) + + +State 68 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type . TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_COMMA shift, and go to state 77 + + +State 69 + + 125 blk_op_time: TK_AT . + + $default reduce using rule 125 (blk_op_time) + + +State 70 + + 126 blk_op_time: TK_EVERY . + + $default reduce using rule 126 (blk_op_time) + + +State 71 + + 122 time_inspection: TK_ID $@40 TK_ATTRIB blk_op_time . number $@41 blk_op_pt $@42 semi_colon $@43 time_inspection2 + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 81 + + +State 72 + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS . blk_function $@7 blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + + TK_FUNCTION shift, and go to state 82 + + $default reduce using rule 37 (blk_function) + + blk_function go to state 83 + + +State 73 + + 83 blk_transition_type: TK_BATCH . + + $default reduce using rule 83 (blk_transition_type) + + +State 74 + + 82 blk_transition_type: TK_CONTINUOUS . + + $default reduce using rule 82 (blk_transition_type) + + +State 75 + + 81 blk_transition_type: TK_DISCRETE . + + $default reduce using rule 81 (blk_transition_type) + + +State 76 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type . TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 + + TK_RIGHT_PARENTHESIS shift, and go to state 84 + + +State 77 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA . TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_ID shift, and go to state 85 + + +State 78 + + 16 number: TK_INTEGER . + + $default reduce using rule 16 (number) + + +State 79 + + 15 number: TK_REAL . + + $default reduce using rule 15 (number) + + +State 80 + + 17 number: TK_EXPONENT . + + $default reduce using rule 17 (number) + + +State 81 + + 122 time_inspection: TK_ID $@40 TK_ATTRIB blk_op_time number . $@41 blk_op_pt $@42 semi_colon $@43 time_inspection2 + + $default reduce using rule 119 ($@41) + + $@41 go to state 86 + + +State 82 + + 36 blk_function: TK_FUNCTION . $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA number $@10 TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + $default reduce using rule 32 ($@8) + + $@8 go to state 87 + + +State 83 + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function . $@7 blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + + $default reduce using rule 24 ($@7) + + $@7 go to state 88 + + +State 84 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS . blk_transition_function $@24 blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 + + TK_FLOW shift, and go to state 89 + TK_TIMING shift, and go to state 90 + + blk_transition_function go to state 91 + + +State 85 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID . $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + $default reduce using rule 106 ($@35) + + $@35 go to state 92 + + +State 86 + + 122 time_inspection: TK_ID $@40 TK_ATTRIB blk_op_time number $@41 . blk_op_pt $@42 semi_colon $@43 time_inspection2 + + TK_PL_TR shift, and go to state 93 + TK_ALL shift, and go to state 94 + + blk_op_pt go to state 95 + + +State 87 + + 36 blk_function: TK_FUNCTION $@8 . TK_LEFT_PARENTHESIS number $@9 TK_COMMA number $@10 TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + TK_LEFT_PARENTHESIS shift, and go to state 96 + + +State 88 + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 . blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 + + TK_INITIAL shift, and go to state 97 + + blk_initial_marking go to state 98 + + +State 89 + + 87 blk_transition_function: TK_FLOW . TK_LEFT_PARENTHESIS number $@27 TK_RIGHT_PARENTHESIS + + TK_LEFT_PARENTHESIS shift, and go to state 99 + + +State 90 + + 85 blk_transition_function: TK_TIMING . TK_LEFT_PARENTHESIS number $@26 TK_RIGHT_PARENTHESIS + + TK_LEFT_PARENTHESIS shift, and go to state 100 + + +State 91 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function . $@24 blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 + + $default reduce using rule 76 ($@24) + + $@24 go to state 101 + + +State 92 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 . TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_COMMA shift, and go to state 102 + + +State 93 + + 127 blk_op_pt: TK_PL_TR . TK_ID + + TK_ID shift, and go to state 103 + + +State 94 + + 128 blk_op_pt: TK_ALL . blk_pl_tr + + TK_PLACES shift, and go to state 104 + TK_TRANSITIONS shift, and go to state 105 + + blk_pl_tr go to state 106 + + +State 95 + + 122 time_inspection: TK_ID $@40 TK_ATTRIB blk_op_time number $@41 blk_op_pt . $@42 semi_colon $@43 time_inspection2 + + $default reduce using rule 120 ($@42) + + $@42 go to state 107 + + +State 96 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS . number $@9 TK_COMMA number $@10 TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 108 + + +State 97 + + 40 blk_initial_marking: TK_INITIAL . TK_MARKING TK_LEFT_BRACKET blk_initial_marking_int TK_RIGHT_BRACKET + + TK_MARKING shift, and go to state 109 + + +State 98 + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking . blk_steady_marking blk_place_arcs blk_place2 + + TK_STEADY shift, and go to state 110 + + $default reduce using rule 54 (blk_steady_marking) + + blk_steady_marking go to state 111 + + +State 99 + + 87 blk_transition_function: TK_FLOW TK_LEFT_PARENTHESIS . number $@27 TK_RIGHT_PARENTHESIS + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 112 + + +State 100 + + 85 blk_transition_function: TK_TIMING TK_LEFT_PARENTHESIS . number $@26 TK_RIGHT_PARENTHESIS + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 113 + + +State 101 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 . blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 + + TK_STEADY shift, and go to state 114 + + $default reduce using rule 89 (blk_steady_transition_function) + + blk_steady_transition_function go to state 115 + + +State 102 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA . number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 116 + + +State 103 + + 127 blk_op_pt: TK_PL_TR TK_ID . + + $default reduce using rule 127 (blk_op_pt) + + +State 104 + + 129 blk_pl_tr: TK_PLACES . + + $default reduce using rule 129 (blk_pl_tr) + + +State 105 + + 130 blk_pl_tr: TK_TRANSITIONS . + + $default reduce using rule 130 (blk_pl_tr) + + +State 106 + + 128 blk_op_pt: TK_ALL blk_pl_tr . + + $default reduce using rule 128 (blk_op_pt) + + +State 107 + + 122 time_inspection: TK_ID $@40 TK_ATTRIB blk_op_time number $@41 blk_op_pt $@42 . semi_colon $@43 time_inspection2 + + TK_SEMICOLON shift, and go to state 19 + + $default reduce using rule 14 (semi_colon) + + semi_colon go to state 117 + + +State 108 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number . $@9 TK_COMMA number $@10 TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + $default reduce using rule 33 ($@9) + + $@9 go to state 118 + + +State 109 + + 40 blk_initial_marking: TK_INITIAL TK_MARKING . TK_LEFT_BRACKET blk_initial_marking_int TK_RIGHT_BRACKET + + TK_LEFT_BRACKET shift, and go to state 119 + + +State 110 + + 53 blk_steady_marking: TK_STEADY . TK_MARKING TK_LEFT_BRACKET blk_steady_marking_int TK_RIGHT_BRACKET + + TK_MARKING shift, and go to state 120 + + +State 111 + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking blk_steady_marking . blk_place_arcs blk_place2 + + TK_OUTPUT shift, and go to state 121 + + $default reduce using rule 70 (blk_place_arcs) + + blk_place_arcs go to state 122 + + +State 112 + + 87 blk_transition_function: TK_FLOW TK_LEFT_PARENTHESIS number . $@27 TK_RIGHT_PARENTHESIS + + $default reduce using rule 86 ($@27) + + $@27 go to state 123 + + +State 113 + + 85 blk_transition_function: TK_TIMING TK_LEFT_PARENTHESIS number . $@26 TK_RIGHT_PARENTHESIS + + $default reduce using rule 84 ($@26) + + $@26 go to state 124 + + +State 114 + + 88 blk_steady_transition_function: TK_STEADY . blk_steady_transition_function_int + + TK_FLOW shift, and go to state 125 + TK_TIMING shift, and go to state 126 + + blk_steady_transition_function_int go to state 127 + + +State 115 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function . $@25 blk_transition_arcs blk_transition2 + + $default reduce using rule 77 ($@25) + + $@25 go to state 128 + + +State 116 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number . $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + $default reduce using rule 107 ($@36) + + $@36 go to state 129 + + +State 117 + + 122 time_inspection: TK_ID $@40 TK_ATTRIB blk_op_time number $@41 blk_op_pt $@42 semi_colon . $@43 time_inspection2 + + $default reduce using rule 121 ($@43) + + $@43 go to state 130 + + +State 118 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 . TK_COMMA number $@10 TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + TK_COMMA shift, and go to state 131 + + +State 119 + + 40 blk_initial_marking: TK_INITIAL TK_MARKING TK_LEFT_BRACKET . blk_initial_marking_int TK_RIGHT_BRACKET + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + TK_LEFT_PARENTHESIS shift, and go to state 132 + + $default reduce using rule 48 (blk_batch) + + number go to state 133 + blk_initial_marking_int go to state 134 + blk_batch go to state 135 + + +State 120 + + 53 blk_steady_marking: TK_STEADY TK_MARKING . TK_LEFT_BRACKET blk_steady_marking_int TK_RIGHT_BRACKET + + TK_LEFT_BRACKET shift, and go to state 136 + + +State 121 + + 69 blk_place_arcs: TK_OUTPUT . TK_ARC TK_ID $@20 blk_place_weight $@21 blk_place_arcs2 + + TK_ARC shift, and go to state 137 + + +State 122 + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking blk_steady_marking blk_place_arcs . blk_place2 + + TK_PLACE shift, and go to state 35 + + $default reduce using rule 27 (blk_place2) + + blk_place go to state 138 + blk_place2 go to state 139 + + +State 123 + + 87 blk_transition_function: TK_FLOW TK_LEFT_PARENTHESIS number $@27 . TK_RIGHT_PARENTHESIS + + TK_RIGHT_PARENTHESIS shift, and go to state 140 + + +State 124 + + 85 blk_transition_function: TK_TIMING TK_LEFT_PARENTHESIS number $@26 . TK_RIGHT_PARENTHESIS + + TK_RIGHT_PARENTHESIS shift, and go to state 141 + + +State 125 + + 93 blk_steady_transition_function_int: TK_FLOW . TK_LEFT_PARENTHESIS number $@29 TK_RIGHT_PARENTHESIS + + TK_LEFT_PARENTHESIS shift, and go to state 142 + + +State 126 + + 91 blk_steady_transition_function_int: TK_TIMING . TK_LEFT_PARENTHESIS number $@28 TK_RIGHT_PARENTHESIS + + TK_LEFT_PARENTHESIS shift, and go to state 143 + + +State 127 + + 88 blk_steady_transition_function: TK_STEADY blk_steady_transition_function_int . + + $default reduce using rule 88 (blk_steady_transition_function) + + +State 128 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function $@25 . blk_transition_arcs blk_transition2 + + TK_OUTPUT shift, and go to state 144 + + $default reduce using rule 97 (blk_transition_arcs) + + blk_transition_arcs go to state 145 + + +State 129 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 . TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_COMMA shift, and go to state 146 + + +State 130 + + 122 time_inspection: TK_ID $@40 TK_ATTRIB blk_op_time number $@41 blk_op_pt $@42 semi_colon $@43 . time_inspection2 + + TK_ID shift, and go to state 47 + + $default reduce using rule 123 (time_inspection) + + time_inspection go to state 147 + time_inspection2 go to state 148 + + +State 131 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA . number $@10 TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 149 + + +State 132 + + 47 blk_batch: TK_LEFT_PARENTHESIS . number $@12 TK_COMMA number $@13 TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 150 + + +State 133 + + 41 blk_initial_marking_int: number . + + $default reduce using rule 41 (blk_initial_marking_int) + + +State 134 + + 40 blk_initial_marking: TK_INITIAL TK_MARKING TK_LEFT_BRACKET blk_initial_marking_int . TK_RIGHT_BRACKET + + TK_RIGHT_BRACKET shift, and go to state 151 + + +State 135 + + 42 blk_initial_marking_int: blk_batch . + + $default reduce using rule 42 (blk_initial_marking_int) + + +State 136 + + 53 blk_steady_marking: TK_STEADY TK_MARKING TK_LEFT_BRACKET . blk_steady_marking_int TK_RIGHT_BRACKET + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + TK_LEFT_PARENTHESIS shift, and go to state 152 + + $default reduce using rule 62 (blk_steady_batch) + + number go to state 153 + blk_steady_marking_int go to state 154 + blk_steady_batch go to state 155 + + +State 137 + + 69 blk_place_arcs: TK_OUTPUT TK_ARC . TK_ID $@20 blk_place_weight $@21 blk_place_arcs2 + + TK_ID shift, and go to state 156 + + +State 138 + + 26 blk_place2: blk_place . + + $default reduce using rule 26 (blk_place2) + + +State 139 + + 25 blk_place: TK_PLACE TK_ID $@6 TK_LEFT_PARENTHESIS blk_place_type TK_RIGHT_PARENTHESIS blk_function $@7 blk_initial_marking blk_steady_marking blk_place_arcs blk_place2 . + + $default reduce using rule 25 (blk_place) + + +State 140 + + 87 blk_transition_function: TK_FLOW TK_LEFT_PARENTHESIS number $@27 TK_RIGHT_PARENTHESIS . + + $default reduce using rule 87 (blk_transition_function) + + +State 141 + + 85 blk_transition_function: TK_TIMING TK_LEFT_PARENTHESIS number $@26 TK_RIGHT_PARENTHESIS . + + $default reduce using rule 85 (blk_transition_function) + + +State 142 + + 93 blk_steady_transition_function_int: TK_FLOW TK_LEFT_PARENTHESIS . number $@29 TK_RIGHT_PARENTHESIS + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 157 + + +State 143 + + 91 blk_steady_transition_function_int: TK_TIMING TK_LEFT_PARENTHESIS . number $@28 TK_RIGHT_PARENTHESIS + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 158 + + +State 144 + + 96 blk_transition_arcs: TK_OUTPUT . TK_ARC TK_ID $@30 blk_transition_weight $@31 blk_transition_arcs2 + + TK_ARC shift, and go to state 159 + + +State 145 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function $@25 blk_transition_arcs . blk_transition2 + + TK_TRANSITION shift, and go to state 44 + + $default reduce using rule 80 (blk_transition2) + + blk_transition go to state 160 + blk_transition2 go to state 161 + + +State 146 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA . number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 162 + + +State 147 + + 124 time_inspection2: time_inspection . + + $default reduce using rule 124 (time_inspection2) + + +State 148 + + 122 time_inspection: TK_ID $@40 TK_ATTRIB blk_op_time number $@41 blk_op_pt $@42 semi_colon $@43 time_inspection2 . + + $default reduce using rule 122 (time_inspection) + + +State 149 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA number . $@10 TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + $default reduce using rule 34 ($@10) + + $@10 go to state 163 + + +State 150 + + 47 blk_batch: TK_LEFT_PARENTHESIS number . $@12 TK_COMMA number $@13 TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + $default reduce using rule 43 ($@12) + + $@12 go to state 164 + + +State 151 + + 40 blk_initial_marking: TK_INITIAL TK_MARKING TK_LEFT_BRACKET blk_initial_marking_int TK_RIGHT_BRACKET . + + $default reduce using rule 40 (blk_initial_marking) + + +State 152 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS . number $@16 TK_COMMA number $@17 TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 165 + + +State 153 + + 55 blk_steady_marking_int: number . + + $default reduce using rule 55 (blk_steady_marking_int) + + +State 154 + + 53 blk_steady_marking: TK_STEADY TK_MARKING TK_LEFT_BRACKET blk_steady_marking_int . TK_RIGHT_BRACKET + + TK_RIGHT_BRACKET shift, and go to state 166 + + +State 155 + + 56 blk_steady_marking_int: blk_steady_batch . + + $default reduce using rule 56 (blk_steady_marking_int) + + +State 156 + + 69 blk_place_arcs: TK_OUTPUT TK_ARC TK_ID . $@20 blk_place_weight $@21 blk_place_arcs2 + + $default reduce using rule 67 ($@20) + + $@20 go to state 167 + + +State 157 + + 93 blk_steady_transition_function_int: TK_FLOW TK_LEFT_PARENTHESIS number . $@29 TK_RIGHT_PARENTHESIS + + $default reduce using rule 92 ($@29) + + $@29 go to state 168 + + +State 158 + + 91 blk_steady_transition_function_int: TK_TIMING TK_LEFT_PARENTHESIS number . $@28 TK_RIGHT_PARENTHESIS + + $default reduce using rule 90 ($@28) + + $@28 go to state 169 + + +State 159 + + 96 blk_transition_arcs: TK_OUTPUT TK_ARC . TK_ID $@30 blk_transition_weight $@31 blk_transition_arcs2 + + TK_ID shift, and go to state 170 + + +State 160 + + 79 blk_transition2: blk_transition . + + $default reduce using rule 79 (blk_transition2) + + +State 161 + + 78 blk_transition: TK_TRANSITION TK_ID $@23 TK_LEFT_PARENTHESIS blk_transition_type TK_RIGHT_PARENTHESIS blk_transition_function $@24 blk_steady_transition_function $@25 blk_transition_arcs blk_transition2 . + + $default reduce using rule 78 (blk_transition) + + +State 162 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number . $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + $default reduce using rule 108 ($@37) + + $@37 go to state 171 + + +State 163 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA number $@10 . TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + TK_COMMA shift, and go to state 172 + + +State 164 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 . TK_COMMA number $@13 TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + TK_COMMA shift, and go to state 173 + + +State 165 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number . $@16 TK_COMMA number $@17 TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + $default reduce using rule 57 ($@16) + + $@16 go to state 174 + + +State 166 + + 53 blk_steady_marking: TK_STEADY TK_MARKING TK_LEFT_BRACKET blk_steady_marking_int TK_RIGHT_BRACKET . + + $default reduce using rule 53 (blk_steady_marking) + + +State 167 + + 69 blk_place_arcs: TK_OUTPUT TK_ARC TK_ID $@20 . blk_place_weight $@21 blk_place_arcs2 + + TK_LEFT_PARENTHESIS shift, and go to state 175 + + $default reduce using rule 74 (blk_place_weight) + + blk_place_weight go to state 176 + + +State 168 + + 93 blk_steady_transition_function_int: TK_FLOW TK_LEFT_PARENTHESIS number $@29 . TK_RIGHT_PARENTHESIS + + TK_RIGHT_PARENTHESIS shift, and go to state 177 + + +State 169 + + 91 blk_steady_transition_function_int: TK_TIMING TK_LEFT_PARENTHESIS number $@28 . TK_RIGHT_PARENTHESIS + + TK_RIGHT_PARENTHESIS shift, and go to state 178 + + +State 170 + + 96 blk_transition_arcs: TK_OUTPUT TK_ARC TK_ID . $@30 blk_transition_weight $@31 blk_transition_arcs2 + + $default reduce using rule 94 ($@30) + + $@30 go to state 179 + + +State 171 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 . TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 + + TK_RIGHT_PARENTHESIS shift, and go to state 180 + + +State 172 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA number $@10 TK_COMMA . number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 181 + + +State 173 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA . number $@13 TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 182 + + +State 174 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 . TK_COMMA number $@17 TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + TK_COMMA shift, and go to state 183 + + +State 175 + + 73 blk_place_weight: TK_LEFT_PARENTHESIS . number $@22 TK_RIGHT_PARENTHESIS + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 184 + + +State 176 + + 69 blk_place_arcs: TK_OUTPUT TK_ARC TK_ID $@20 blk_place_weight . $@21 blk_place_arcs2 + + $default reduce using rule 68 ($@21) + + $@21 go to state 185 + + +State 177 + + 93 blk_steady_transition_function_int: TK_FLOW TK_LEFT_PARENTHESIS number $@29 TK_RIGHT_PARENTHESIS . + + $default reduce using rule 93 (blk_steady_transition_function_int) + + +State 178 + + 91 blk_steady_transition_function_int: TK_TIMING TK_LEFT_PARENTHESIS number $@28 TK_RIGHT_PARENTHESIS . + + $default reduce using rule 91 (blk_steady_transition_function_int) + + +State 179 + + 96 blk_transition_arcs: TK_OUTPUT TK_ARC TK_ID $@30 . blk_transition_weight $@31 blk_transition_arcs2 + + TK_LEFT_PARENTHESIS shift, and go to state 186 + + $default reduce using rule 101 (blk_transition_weight) + + blk_transition_weight go to state 187 + + +State 180 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS . semi_colon $@38 controlled_events2 + + TK_SEMICOLON shift, and go to state 19 + + $default reduce using rule 14 (semi_colon) + + semi_colon go to state 188 + + +State 181 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA number $@10 TK_COMMA number . $@11 blk_triangular_place TK_RIGHT_PARENTHESIS + + $default reduce using rule 35 ($@11) + + $@11 go to state 189 + + +State 182 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number . $@13 TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + $default reduce using rule 44 ($@13) + + $@13 go to state 190 + + +State 183 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA . number $@17 TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 191 + + +State 184 + + 73 blk_place_weight: TK_LEFT_PARENTHESIS number . $@22 TK_RIGHT_PARENTHESIS + + $default reduce using rule 72 ($@22) + + $@22 go to state 192 + + +State 185 + + 69 blk_place_arcs: TK_OUTPUT TK_ARC TK_ID $@20 blk_place_weight $@21 . blk_place_arcs2 + + TK_OUTPUT shift, and go to state 121 + + $default reduce using rule 70 (blk_place_arcs) + + blk_place_arcs go to state 193 + blk_place_arcs2 go to state 194 + + +State 186 + + 100 blk_transition_weight: TK_LEFT_PARENTHESIS . number $@32 TK_RIGHT_PARENTHESIS + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 195 + + +State 187 + + 96 blk_transition_arcs: TK_OUTPUT TK_ARC TK_ID $@30 blk_transition_weight . $@31 blk_transition_arcs2 + + $default reduce using rule 95 ($@31) + + $@31 go to state 196 + + +State 188 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon . $@38 controlled_events2 + + $default reduce using rule 109 ($@38) + + $@38 go to state 197 + + +State 189 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA number $@10 TK_COMMA number $@11 . blk_triangular_place TK_RIGHT_PARENTHESIS + + TK_COMMA shift, and go to state 198 + + $default reduce using rule 39 (blk_triangular_place) + + blk_triangular_place go to state 199 + + +State 190 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number $@13 . TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + TK_COMMA shift, and go to state 200 + + +State 191 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number . $@17 TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + $default reduce using rule 58 ($@17) + + $@17 go to state 201 + + +State 192 + + 73 blk_place_weight: TK_LEFT_PARENTHESIS number $@22 . TK_RIGHT_PARENTHESIS + + TK_RIGHT_PARENTHESIS shift, and go to state 202 + + +State 193 + + 71 blk_place_arcs2: blk_place_arcs . + + $default reduce using rule 71 (blk_place_arcs2) + + +State 194 + + 69 blk_place_arcs: TK_OUTPUT TK_ARC TK_ID $@20 blk_place_weight $@21 blk_place_arcs2 . + + $default reduce using rule 69 (blk_place_arcs) + + +State 195 + + 100 blk_transition_weight: TK_LEFT_PARENTHESIS number . $@32 TK_RIGHT_PARENTHESIS + + $default reduce using rule 99 ($@32) + + $@32 go to state 203 + + +State 196 + + 96 blk_transition_arcs: TK_OUTPUT TK_ARC TK_ID $@30 blk_transition_weight $@31 . blk_transition_arcs2 + + TK_OUTPUT shift, and go to state 144 + + $default reduce using rule 97 (blk_transition_arcs) + + blk_transition_arcs go to state 204 + blk_transition_arcs2 go to state 205 + + +State 197 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 . controlled_events2 + + TK_ID shift, and go to state 38 + + $default reduce using rule 111 (controlled_events) + + controlled_events go to state 206 + controlled_events2 go to state 207 + + +State 198 + + 38 blk_triangular_place: TK_COMMA . number + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 208 + + +State 199 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA number $@10 TK_COMMA number $@11 blk_triangular_place . TK_RIGHT_PARENTHESIS + + TK_RIGHT_PARENTHESIS shift, and go to state 209 + + +State 200 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number $@13 TK_COMMA . number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 210 + + +State 201 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number $@17 . TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + TK_COMMA shift, and go to state 211 + + +State 202 + + 73 blk_place_weight: TK_LEFT_PARENTHESIS number $@22 TK_RIGHT_PARENTHESIS . + + $default reduce using rule 73 (blk_place_weight) + + +State 203 + + 100 blk_transition_weight: TK_LEFT_PARENTHESIS number $@32 . TK_RIGHT_PARENTHESIS + + TK_RIGHT_PARENTHESIS shift, and go to state 212 + + +State 204 + + 98 blk_transition_arcs2: blk_transition_arcs . + + $default reduce using rule 98 (blk_transition_arcs2) + + +State 205 + + 96 blk_transition_arcs: TK_OUTPUT TK_ARC TK_ID $@30 blk_transition_weight $@31 blk_transition_arcs2 . + + $default reduce using rule 96 (blk_transition_arcs) + + +State 206 + + 112 controlled_events2: controlled_events . + + $default reduce using rule 112 (controlled_events2) + + +State 207 + + 110 controlled_events: TK_ID $@34 TK_ATTRIB TK_LEFT_PARENTHESIS controlled_events_type TK_COMMA TK_ID $@35 TK_COMMA number $@36 TK_COMMA number $@37 TK_RIGHT_PARENTHESIS semi_colon $@38 controlled_events2 . + + $default reduce using rule 110 (controlled_events) + + +State 208 + + 38 blk_triangular_place: TK_COMMA number . + + $default reduce using rule 38 (blk_triangular_place) + + +State 209 + + 36 blk_function: TK_FUNCTION $@8 TK_LEFT_PARENTHESIS number $@9 TK_COMMA number $@10 TK_COMMA number $@11 blk_triangular_place TK_RIGHT_PARENTHESIS . + + $default reduce using rule 36 (blk_function) + + +State 210 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number $@13 TK_COMMA number . $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + $default reduce using rule 45 ($@14) + + $@14 go to state 213 + + +State 211 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number $@17 TK_COMMA . number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 214 + + +State 212 + + 100 blk_transition_weight: TK_LEFT_PARENTHESIS number $@32 TK_RIGHT_PARENTHESIS . + + $default reduce using rule 100 (blk_transition_weight) + + +State 213 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number $@13 TK_COMMA number $@14 . blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + TK_COMMA shift, and go to state 215 + + $default reduce using rule 52 (blk_triangular_batch) + + blk_triangular_batch go to state 216 + + +State 214 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number $@17 TK_COMMA number . $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + $default reduce using rule 59 ($@18) + + $@18 go to state 217 + + +State 215 + + 51 blk_triangular_batch: TK_COMMA . number + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 218 + + +State 216 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number $@13 TK_COMMA number $@14 blk_triangular_batch . TK_RIGHT_PARENTHESIS $@15 blk_batch2 + + TK_RIGHT_PARENTHESIS shift, and go to state 219 + + +State 217 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number $@17 TK_COMMA number $@18 . blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + TK_COMMA shift, and go to state 220 + + $default reduce using rule 66 (blk_steady_triangular_batch) + + blk_steady_triangular_batch go to state 221 + + +State 218 + + 51 blk_triangular_batch: TK_COMMA number . + + $default reduce using rule 51 (blk_triangular_batch) + + +State 219 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number $@13 TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS . $@15 blk_batch2 + + $default reduce using rule 46 ($@15) + + $@15 go to state 222 + + +State 220 + + 65 blk_steady_triangular_batch: TK_COMMA . number + + TK_INTEGER shift, and go to state 78 + TK_REAL shift, and go to state 79 + TK_EXPONENT shift, and go to state 80 + + number go to state 223 + + +State 221 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number $@17 TK_COMMA number $@18 blk_steady_triangular_batch . TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 + + TK_RIGHT_PARENTHESIS shift, and go to state 224 + + +State 222 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number $@13 TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 . blk_batch2 + + TK_COMMA shift, and go to state 225 + + $default reduce using rule 50 (blk_batch2) + + blk_batch2 go to state 226 + + +State 223 + + 65 blk_steady_triangular_batch: TK_COMMA number . + + $default reduce using rule 65 (blk_steady_triangular_batch) + + +State 224 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number $@17 TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS . $@19 blk_steady_batch2 + + $default reduce using rule 60 ($@19) + + $@19 go to state 227 + + +State 225 + + 49 blk_batch2: TK_COMMA . blk_batch + + TK_LEFT_PARENTHESIS shift, and go to state 132 + + $default reduce using rule 48 (blk_batch) + + blk_batch go to state 228 + + +State 226 + + 47 blk_batch: TK_LEFT_PARENTHESIS number $@12 TK_COMMA number $@13 TK_COMMA number $@14 blk_triangular_batch TK_RIGHT_PARENTHESIS $@15 blk_batch2 . + + $default reduce using rule 47 (blk_batch) + + +State 227 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number $@17 TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 . blk_steady_batch2 + + TK_COMMA shift, and go to state 229 + + $default reduce using rule 64 (blk_steady_batch2) + + blk_steady_batch2 go to state 230 + + +State 228 + + 49 blk_batch2: TK_COMMA blk_batch . + + $default reduce using rule 49 (blk_batch2) + + +State 229 + + 63 blk_steady_batch2: TK_COMMA . blk_steady_batch + + TK_LEFT_PARENTHESIS shift, and go to state 152 + + $default reduce using rule 62 (blk_steady_batch) + + blk_steady_batch go to state 231 + + +State 230 + + 61 blk_steady_batch: TK_LEFT_PARENTHESIS number $@16 TK_COMMA number $@17 TK_COMMA number $@18 blk_steady_triangular_batch TK_RIGHT_PARENTHESIS $@19 blk_steady_batch2 . + + $default reduce using rule 61 (blk_steady_batch) + + +State 231 + + 63 blk_steady_batch2: TK_COMMA blk_steady_batch . + + $default reduce using rule 63 (blk_steady_batch2) diff --git a/src/interf/y.tab.cpp b/src/interf/y.tab.cpp new file mode 100644 index 0000000..b91798b --- /dev/null +++ b/src/interf/y.tab.cpp @@ -0,0 +1,2642 @@ +/* A Bison parser, made by GNU Bison 3.5.1. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.5.1" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* First part of user prologue. */ +#line 1 "src/interf/glc.y" + +//====================================================================================// +// // +// Parser and Semantic Analysis // +// // +//====================================================================================// +// This File: glc.y Tool: YACC // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 15/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 15/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +// YACC is a general-purpose parser generator that converts a context-free grammar // +// a C program.In this module are make the actions to generate the internal SAN's // +// tables and the others functionalities of this textual interface for PEPS. // +//====================================================================================// +#include "bpnfile.h" +#include "simuleau.h" + +//====================================================================================// +// Global variables // +//====================================================================================// + +extern BPN *bpn; // Network structure +extern Schedule *schedule; // schedule structure + +int not_error = 1; +int is_integer = 1; + +int tour; // Set the times that the parser was called, the first to count the number + // of places, the number of transitions and others + +//====================================================================================// +// Variables // +//====================================================================================// + + int discreteplaces; // number of discrete places + int continuousplaces; // number of continuous places + int batchplaces; // number of batch places + int triangularplaces; // number of triangular batch places + + int currentdiscreteplace; // index of the current discrete place used to add place + int currentcontinuousplace; // index of the current continuous place + int currentbatchplace; // index of the current batch place + int currenttriangularplace; // index of the current triangular batch place + + int discretetransitions; // number of discrete transitions + int continuoustransitions; // number of continuous transitions + int batchtransitions; // number of batch transitions + + int currentdiscretetransition; // index of the current discrete place used to add place + int currentcontinuoustransition;// index of the current continuous place + int currentbatchtransition; // index of the current batch place + + place_id idplacenumber; // number of the place id + simuleau_name idplace; // name of the place id + place_type ptype; // place type + double pdensity; // place density + double pspeed; // place speed + double plength; // place length + double pflow; // place flow + + double bdensity; // batch density + double bspeed; // batch speed + double blength; // batch length + double bposition; // batch position + + trans_id idtransitionnumber; // number of the transition id + simuleau_name idtransition; // name of the transition id + trans_type ttype; // transition type + double ttime; // time of the discrete transitions + double tsteadytime; // steady time of the discrete transitions + double tflow; // flow of the continuous and batch transitions + double tsteadyflow; // steady flow of the continuous and batch transitions + + double arcweight; // arc weight + + simuleau_name idcevent; // name of the controlled event + ev_type cetype; // type of the controlled event + simuleau_name idnode; // name of the place or transition + double cedate; // controlled event date + double cevalue; // new value of the flow/speed + + simuleau_name idbreakpoint; // name of the breakpoint + breakpoint_type bptype; // type of the breakpoint (at (?) or every (*)) + double bpdate; // date or frequency + + +//====================================================================================// +// Parser variables // +//====================================================================================// + +extern int yynerrs; // Variable of the YACC generator to count the number of errors. +extern int yylineno; // Variable of the YACC generator to count the current line + +extern int yylex(void); // Get the next token +extern void yyrestart(FILE *input_file); +extern char *yytext; +extern FILE *yyin; // Input file + + +//====================================================================================// +// Function errors // +//====================================================================================// +// These functions analysis which error occurred and put the error into a message // +// more specific. // +//====================================================================================// + + +//==================================================================================== +// Function that YACC use to put syntatic message errors +//==================================================================================== +extern void yyerror(string s) +{ + yynerrs++; + not_error = 0; + Syntatic_Error(yynerrs, yylineno, s, yytext); +} + +//==================================================================================== +// Function to put semantic error messages +//==================================================================================== +void type_error(char* text, const char* error_number) +{ + yynerrs++; + not_error = 0; + Semantic_Error_YACC(yynerrs, yylineno, text, error_number); +} + + + +#line 202 "src/interf/y.tab.cpp" + +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast<Type> (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Use api.header.include to #include this header + instead of duplicating it here. */ +#ifndef YY_YY_SRC_INTERF_Y_TAB_HPP_INCLUDED +# define YY_YY_SRC_INTERF_Y_TAB_HPP_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + TK_ARC = 258, + TK_BATCH = 259, + TK_CONTINUOUS = 260, + TK_CONTROLLED = 261, + TK_DESCRIPTION = 262, + TK_DISCRETE = 263, + TK_EVENTS = 264, + TK_FLOW = 265, + TK_FUNCTION = 266, + TK_INITIAL = 267, + TK_INSPECTION = 268, + TK_LENGTH = 269, + TK_MARKING = 270, + TK_MODEL = 271, + TK_NETWORK = 272, + TK_OUTPUT = 273, + TK_PLACE = 274, + TK_PLACES = 275, + TK_SPEED = 276, + TK_STEADY = 277, + TK_TIME = 278, + TK_TIMING = 279, + TK_TRANSITION = 280, + TK_TRANSITIONS = 281, + TK_TRIANGULAR = 282, + TK_UNITY = 283, + TK_ID = 284, + TK_INTEGER = 285, + TK_REAL = 286, + TK_EXPONENT = 287, + TK_AT = 288, + TK_EVERY = 289, + TK_LEFT_BRACKET = 290, + TK_RIGHT_BRACKET = 291, + TK_PL_TR = 292, + TK_ALL = 293, + TK_LEFT_PARENTHESIS = 294, + TK_RIGHT_PARENTHESIS = 295, + TK_LEFT_SQUARE_BRACKET = 296, + TK_RIGHT_SQUARE_BRACKET = 297, + TK_SEMICOLON = 298, + TK_COMMA = 299, + TK_ATTRIB = 300, + TK_COLON = 301 + }; +#endif +/* Tokens. */ +#define TK_ARC 258 +#define TK_BATCH 259 +#define TK_CONTINUOUS 260 +#define TK_CONTROLLED 261 +#define TK_DESCRIPTION 262 +#define TK_DISCRETE 263 +#define TK_EVENTS 264 +#define TK_FLOW 265 +#define TK_FUNCTION 266 +#define TK_INITIAL 267 +#define TK_INSPECTION 268 +#define TK_LENGTH 269 +#define TK_MARKING 270 +#define TK_MODEL 271 +#define TK_NETWORK 272 +#define TK_OUTPUT 273 +#define TK_PLACE 274 +#define TK_PLACES 275 +#define TK_SPEED 276 +#define TK_STEADY 277 +#define TK_TIME 278 +#define TK_TIMING 279 +#define TK_TRANSITION 280 +#define TK_TRANSITIONS 281 +#define TK_TRIANGULAR 282 +#define TK_UNITY 283 +#define TK_ID 284 +#define TK_INTEGER 285 +#define TK_REAL 286 +#define TK_EXPONENT 287 +#define TK_AT 288 +#define TK_EVERY 289 +#define TK_LEFT_BRACKET 290 +#define TK_RIGHT_BRACKET 291 +#define TK_PL_TR 292 +#define TK_ALL 293 +#define TK_LEFT_PARENTHESIS 294 +#define TK_RIGHT_PARENTHESIS 295 +#define TK_LEFT_SQUARE_BRACKET 296 +#define TK_RIGHT_SQUARE_BRACKET 297 +#define TK_SEMICOLON 298 +#define TK_COMMA 299 +#define TK_ATTRIB 300 +#define TK_COLON 301 + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + +int yyparse (void); + +#endif /* !YY_YY_SRC_INTERF_Y_TAB_HPP_INCLUDED */ + + + +#ifdef short +# undef short +#endif + +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + <limits.h> and (if available) <stdint.h> are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include <limits.h> /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include <stdint.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif +#endif + +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; +#endif + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned +# endif +#endif + +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + +/* Stored state numbers (used for stacks). */ +typedef yytype_uint8 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYPTRDIFF_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 6 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 147 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 47 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 92 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 131 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 232 + +#define YYUNDEFTOK 2 +#define YYMAXUTOK 301 + + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex. */ +static const yytype_int8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46 +}; + +#if YYDEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_int16 yyrline[] = +{ + 0, 155, 155, 163, 167, 167, 168, 172, 176, 176, + 177, 181, 181, 182, 186, 187, 191, 192, 193, 202, + 206, 206, 210, 210, 220, 227, 219, 252, 253, 257, + 258, 259, 260, 268, 271, 272, 273, 268, 274, 278, + 282, 292, 296, 314, 318, 318, 319, 320, 318, 337, + 341, 342, 346, 347, 355, 356, 360, 378, 382, 382, + 383, 384, 382, 401, 405, 406, 410, 411, 419, 420, + 419, 436, 440, 444, 444, 445, 456, 463, 467, 455, + 489, 490, 494, 495, 496, 500, 500, 501, 501, 505, + 506, 510, 510, 511, 511, 521, 522, 521, 533, 537, + 541, 541, 542, 550, 550, 551, 555, 555, 556, 556, + 557, 555, 596, 600, 604, 605, 613, 613, 614, 618, + 618, 618, 619, 618, 633, 637, 641, 642, 646, 647, + 651, 652 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || 0 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TK_ARC", "TK_BATCH", "TK_CONTINUOUS", + "TK_CONTROLLED", "TK_DESCRIPTION", "TK_DISCRETE", "TK_EVENTS", "TK_FLOW", + "TK_FUNCTION", "TK_INITIAL", "TK_INSPECTION", "TK_LENGTH", "TK_MARKING", + "TK_MODEL", "TK_NETWORK", "TK_OUTPUT", "TK_PLACE", "TK_PLACES", + "TK_SPEED", "TK_STEADY", "TK_TIME", "TK_TIMING", "TK_TRANSITION", + "TK_TRANSITIONS", "TK_TRIANGULAR", "TK_UNITY", "TK_ID", "TK_INTEGER", + "TK_REAL", "TK_EXPONENT", "TK_AT", "TK_EVERY", "TK_LEFT_BRACKET", + "TK_RIGHT_BRACKET", "TK_PL_TR", "TK_ALL", "TK_LEFT_PARENTHESIS", + "TK_RIGHT_PARENTHESIS", "TK_LEFT_SQUARE_BRACKET", + "TK_RIGHT_SQUARE_BRACKET", "TK_SEMICOLON", "TK_COMMA", "TK_ATTRIB", + "TK_COLON", "$accept", "start", "blk_def", "blk_model", "$@1", + "blk_unity", "blk_lenght", "$@2", "blk_time", "$@3", "semi_colon", + "number", "blk_net", "blk_places", "$@4", "blk_transitions", "$@5", + "blk_place", "$@6", "$@7", "blk_place2", "blk_place_type", + "blk_function", "$@8", "$@9", "$@10", "$@11", "blk_triangular_place", + "blk_initial_marking", "blk_initial_marking_int", "blk_batch", "$@12", + "$@13", "$@14", "$@15", "blk_batch2", "blk_triangular_batch", + "blk_steady_marking", "blk_steady_marking_int", "blk_steady_batch", + "$@16", "$@17", "$@18", "$@19", "blk_steady_batch2", + "blk_steady_triangular_batch", "blk_place_arcs", "$@20", "$@21", + "blk_place_arcs2", "blk_place_weight", "$@22", "blk_transition", "$@23", + "$@24", "$@25", "blk_transition2", "blk_transition_type", + "blk_transition_function", "$@26", "$@27", + "blk_steady_transition_function", "blk_steady_transition_function_int", + "$@28", "$@29", "blk_transition_arcs", "$@30", "$@31", + "blk_transition_arcs2", "blk_transition_weight", "$@32", + "blk_controlled_events", "$@33", "controlled_events", "$@34", "$@35", + "$@36", "$@37", "$@38", "controlled_events2", "controlled_events_type", + "blk_time_inspection", "$@39", "time_inspection", "$@40", "$@41", "$@42", + "$@43", "time_inspection2", "blk_op_time", "blk_op_pt", "blk_pl_tr", YY_NULLPTR +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_int16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301 +}; +# endif + +#define YYPACT_NINF (-113) + +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) + +#define YYTABLE_NINF (-1) + +#define yytable_value_is_error(Yyn) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + -8, 10, 20, 11, 26, -113, -113, 38, 40, 21, + -113, 27, 9, 33, 45, 32, 13, 28, -113, -113, + -113, -113, 34, -113, 46, -113, 35, 16, 43, -113, + -113, 36, -113, -113, 39, 41, -113, 42, -113, -113, + 44, 9, -113, -113, 47, -113, 18, -113, -113, -113, + 9, 30, -113, 48, 29, -113, -2, 50, 0, 1, + -113, -113, -113, -113, 31, 14, -113, -113, 37, -113, + -113, 12, 61, -113, -113, -113, 52, 53, -113, -113, + -113, -113, -113, -113, 2, -113, -5, 51, 63, 54, + 55, -113, 56, 57, -9, -113, 12, 64, 62, 12, + 12, 73, 12, -113, -113, -113, -113, 9, -113, 66, + 68, 67, -113, -113, 3, -113, -113, -113, 58, -16, + 69, 93, 43, 59, 70, 72, 74, -113, 79, 65, + 44, 12, 12, -113, 71, -113, -1, 77, -113, -113, + -113, -113, 12, 12, 95, 42, 12, -113, -113, -113, + -113, -113, 12, -113, 76, -113, -113, -113, -113, 85, + -113, -113, -113, 75, 78, -113, -113, 82, 83, 84, + -113, 86, 12, 12, 87, 12, -113, -113, -113, 88, + 9, -113, -113, 12, -113, 67, 12, -113, -113, 89, + 90, -113, 92, -113, -113, -113, 79, 36, 12, 96, + 12, 91, -113, 97, -113, -113, -113, -113, -113, -113, + -113, 12, -113, 94, -113, 12, 100, 98, -113, -113, + 12, 101, 99, -113, -113, 105, -113, 102, -113, 106, + -113, -113 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 6, 0, 0, 0, 10, 4, 1, 0, 105, 0, + 3, 13, 15, 0, 0, 118, 0, 0, 7, 14, + 5, 20, 0, 103, 0, 2, 0, 0, 0, 22, + 19, 112, 116, 8, 0, 0, 21, 0, 106, 104, + 124, 15, 11, 24, 0, 23, 0, 119, 117, 9, + 15, 0, 76, 0, 0, 12, 0, 0, 0, 0, + 31, 30, 29, 32, 0, 0, 114, 115, 0, 126, + 127, 0, 38, 84, 83, 82, 0, 0, 17, 16, + 18, 120, 33, 25, 0, 107, 0, 0, 0, 0, + 0, 77, 0, 0, 0, 121, 0, 0, 55, 0, + 0, 90, 0, 128, 130, 131, 129, 15, 34, 0, + 0, 71, 87, 85, 0, 78, 108, 122, 0, 49, + 0, 0, 28, 0, 0, 0, 0, 89, 98, 0, + 124, 0, 0, 42, 0, 43, 63, 0, 27, 26, + 88, 86, 0, 0, 0, 81, 0, 125, 123, 35, + 44, 41, 0, 56, 0, 57, 68, 93, 91, 0, + 80, 79, 109, 0, 0, 58, 54, 75, 0, 0, + 95, 0, 0, 0, 0, 0, 69, 94, 92, 102, + 15, 36, 45, 0, 73, 71, 0, 96, 110, 40, + 0, 59, 0, 72, 70, 100, 98, 112, 0, 0, + 0, 0, 74, 0, 99, 97, 113, 111, 39, 37, + 46, 0, 101, 53, 60, 0, 0, 67, 52, 47, + 0, 0, 51, 66, 61, 49, 48, 65, 50, 63, + 62, 64 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -113, -113, -113, -113, -113, -113, -113, -113, -113, -113, + -41, -95, -113, -113, -113, -113, -113, -14, -113, -113, + -113, -113, -113, -113, -113, -113, -113, -113, -113, -113, + -110, -113, -113, -113, -113, -113, -113, -113, -113, -112, + -113, -113, -113, -113, -113, -113, -67, -113, -113, -113, + -113, -113, -17, -113, -113, -113, -113, -113, -113, -113, + -113, -113, -113, -113, -113, -66, -113, -113, -113, -113, + -113, -113, -113, -68, -113, -113, -113, -113, -113, -113, + -113, -113, -113, 17, -113, -113, -113, -113, -113, -113, + -113, -113 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 2, 3, 4, 12, 10, 11, 41, 18, 50, + 20, 81, 8, 22, 28, 30, 37, 36, 51, 88, + 139, 64, 83, 87, 118, 163, 189, 199, 98, 134, + 135, 164, 190, 213, 222, 226, 216, 111, 154, 155, + 174, 201, 217, 227, 230, 221, 122, 167, 185, 194, + 176, 192, 45, 57, 101, 128, 161, 76, 91, 124, + 123, 115, 127, 169, 168, 145, 179, 196, 205, 187, + 203, 15, 31, 39, 46, 92, 129, 171, 197, 207, + 68, 25, 40, 48, 54, 86, 107, 130, 148, 71, + 95, 106 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_uint8 yytable[] = +{ + 49, 108, 60, 61, 112, 113, 62, 116, 1, 55, + 66, 104, 89, 125, 78, 79, 80, 105, 73, 74, + 6, 67, 75, 132, 133, 63, 90, 126, 7, 78, + 79, 80, 93, 94, 69, 70, 149, 150, 152, 5, + 9, 153, 78, 79, 80, 13, 14, 157, 158, 16, + 17, 162, 19, 21, 23, 24, 27, 165, 26, 32, + 29, 34, 35, 53, 33, 38, 117, 44, 42, 56, + 43, 72, 82, 47, 59, 97, 52, 181, 182, 109, + 184, 77, 85, 120, 110, 121, 103, 58, 191, 65, + 96, 195, 84, 99, 100, 114, 137, 144, 159, 140, + 102, 119, 131, 208, 136, 210, 156, 151, 138, 146, + 141, 142, 166, 143, 170, 228, 214, 231, 193, 172, + 218, 175, 173, 177, 178, 223, 180, 186, 160, 206, + 204, 183, 202, 198, 200, 211, 209, 212, 215, 188, + 219, 224, 220, 225, 132, 152, 229, 147 +}; + +static const yytype_uint8 yycheck[] = +{ + 41, 96, 4, 5, 99, 100, 8, 102, 16, 50, + 10, 20, 10, 10, 30, 31, 32, 26, 4, 5, + 0, 21, 8, 39, 119, 27, 24, 24, 17, 30, + 31, 32, 37, 38, 33, 34, 131, 132, 39, 29, + 14, 136, 30, 31, 32, 7, 6, 142, 143, 28, + 23, 146, 43, 20, 9, 23, 28, 152, 45, 13, + 26, 45, 19, 45, 29, 29, 107, 25, 29, 39, + 29, 40, 11, 29, 45, 12, 29, 172, 173, 15, + 175, 44, 29, 15, 22, 18, 29, 39, 183, 39, + 39, 186, 40, 39, 39, 22, 3, 18, 3, 40, + 44, 35, 44, 198, 35, 200, 29, 36, 122, 44, + 40, 39, 36, 39, 29, 225, 211, 229, 185, 44, + 215, 39, 44, 40, 40, 220, 40, 39, 145, 197, + 196, 44, 40, 44, 44, 44, 40, 40, 44, 180, + 40, 40, 44, 44, 39, 39, 44, 130 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 16, 48, 49, 50, 29, 0, 17, 59, 14, + 52, 53, 51, 7, 6, 118, 28, 23, 55, 43, + 57, 20, 60, 9, 23, 128, 45, 28, 61, 26, + 62, 119, 13, 29, 45, 19, 64, 63, 29, 120, + 129, 54, 29, 29, 25, 99, 121, 29, 130, 57, + 56, 65, 29, 45, 131, 57, 39, 100, 39, 45, + 4, 5, 8, 27, 68, 39, 10, 21, 127, 33, + 34, 136, 40, 4, 5, 8, 104, 44, 30, 31, + 32, 58, 11, 69, 40, 29, 132, 70, 66, 10, + 24, 105, 122, 37, 38, 137, 39, 12, 75, 39, + 39, 101, 44, 29, 20, 26, 138, 133, 58, 15, + 22, 84, 58, 58, 22, 108, 58, 57, 71, 35, + 15, 18, 93, 107, 106, 10, 24, 109, 102, 123, + 134, 44, 39, 58, 76, 77, 35, 3, 64, 67, + 40, 40, 39, 39, 18, 112, 44, 130, 135, 58, + 58, 36, 39, 58, 85, 86, 29, 58, 58, 3, + 99, 103, 58, 72, 78, 58, 36, 94, 111, 110, + 29, 124, 44, 44, 87, 39, 97, 40, 40, 113, + 40, 58, 58, 44, 58, 95, 39, 116, 57, 73, + 79, 58, 98, 93, 96, 58, 114, 125, 44, 74, + 44, 88, 40, 117, 112, 115, 120, 126, 58, 40, + 58, 44, 40, 80, 58, 44, 83, 89, 58, 40, + 44, 92, 81, 58, 40, 44, 82, 90, 77, 44, + 91, 86 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 47, 48, 49, 51, 50, 50, 52, 54, 53, + 53, 56, 55, 55, 57, 57, 58, 58, 58, 59, + 61, 60, 63, 62, 65, 66, 64, 67, 67, 68, + 68, 68, 68, 70, 71, 72, 73, 69, 69, 74, + 74, 75, 76, 76, 78, 79, 80, 81, 77, 77, + 82, 82, 83, 83, 84, 84, 85, 85, 87, 88, + 89, 90, 86, 86, 91, 91, 92, 92, 94, 95, + 93, 93, 96, 98, 97, 97, 100, 101, 102, 99, + 103, 103, 104, 104, 104, 106, 105, 107, 105, 108, + 108, 110, 109, 111, 109, 113, 114, 112, 112, 115, + 117, 116, 116, 119, 118, 118, 121, 122, 123, 124, + 125, 120, 120, 126, 127, 127, 129, 128, 128, 131, + 132, 133, 134, 130, 130, 135, 136, 136, 137, 137, + 138, 138 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_int8 yyr2[] = +{ + 0, 2, 4, 2, 0, 4, 0, 2, 0, 6, + 0, 0, 6, 0, 1, 0, 1, 1, 1, 4, + 0, 3, 0, 3, 0, 0, 12, 1, 0, 1, + 1, 1, 1, 0, 0, 0, 0, 13, 0, 2, + 0, 5, 1, 1, 0, 0, 0, 0, 13, 0, + 2, 0, 2, 0, 5, 0, 1, 1, 0, 0, + 0, 0, 13, 0, 2, 0, 2, 0, 0, 0, + 7, 0, 1, 0, 4, 0, 0, 0, 0, 12, + 1, 0, 1, 1, 1, 0, 5, 0, 5, 2, + 0, 0, 5, 0, 5, 0, 0, 7, 0, 1, + 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 18, 0, 1, 1, 1, 0, 4, 0, 0, + 0, 0, 0, 11, 0, 1, 1, 1, 2, 2, + 1, 1 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep) +{ + FILE *yyoutput = yyo; + YYUSE (yyoutput); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyo, yytoknum[yytype], *yyvaluep); +# endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ + +static void +yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep) +{ + YYFPRINTF (yyo, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyo, yytype, yyvaluep); + YYFPRINTF (yyo, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, int yyrule) +{ + int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[+yyssp[yyi + 1 - yynrhs]], + &yyvsp[(yyi + 1) - (yynrhs)] + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S))) +# else +/* Return the length of YYSTR. */ +static YYPTRDIFF_T +yystrlen (const char *yystr) +{ + YYPTRDIFF_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYPTRDIFF_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYPTRDIFF_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + else + goto append; + + append: + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (yyres) + return yystpcpy (yyres, yystr) - yyres; + else + return yystrlen (yystr); +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg, + yy_state_t *yyssp, int yytoken) +{ + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat: reported tokens (one for the "unexpected", + one per "expected"). */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Actual size of YYARG. */ + int yycount = 0; + /* Cumulated lengths of YYARG. */ + YYPTRDIFF_T yysize = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[+*yyssp]; + YYPTRDIFF_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + yysize = yysize0; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYPTRDIFF_T yysize1 + = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else + return 2; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + default: /* Avoid compiler warnings. */ + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + /* Don't count the "%s"s in the final size, but reserve room for + the terminator. */ + YYPTRDIFF_T yysize1 = yysize + (yystrlen (yyformat) - 2 * yycount) + 1; + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else + return 2; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + ++yyp; + ++yyformat; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +{ + YYUSE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + yy_state_fast_t yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss; + yy_state_t *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYPTRDIFF_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + + +/*------------------------------------------------------------. +| yynewstate -- push a new state, which is found in yystate. | +`------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else + { + /* Get the current used size of the three stacks, in elements. */ + YYPTRDIFF_T yysize = yyssp - yyss + 1; + +# if defined yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yystacksize); + yyss = yyss1; + yyvs = yyvs1; + } +# else /* defined YYSTACK_RELOCATE */ + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((stderr, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + /* Discard the shifted token. */ + yychar = YYEMPTY; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 4: +#line 167 "src/interf/glc.y" + {if (tour == 1) bpn->PutName(yytext);} +#line 1694 "src/interf/y.tab.cpp" + break; + + case 8: +#line 176 "src/interf/glc.y" + {PRF::prf.Length_Unity(yytext);} +#line 1700 "src/interf/y.tab.cpp" + break; + + case 11: +#line 181 "src/interf/glc.y" + {PRF::prf.Time_Unity(yytext);} +#line 1706 "src/interf/y.tab.cpp" + break; + + case 16: +#line 191 "src/interf/glc.y" + { is_integer = 0; } +#line 1712 "src/interf/y.tab.cpp" + break; + + case 17: +#line 192 "src/interf/glc.y" + { is_integer = 1; } +#line 1718 "src/interf/y.tab.cpp" + break; + + case 18: +#line 193 "src/interf/glc.y" + { is_integer = 0; } +#line 1724 "src/interf/y.tab.cpp" + break; + + case 20: +#line 206 "src/interf/glc.y" + { cout << "Compiling places\n";} +#line 1730 "src/interf/y.tab.cpp" + break; + + case 22: +#line 210 "src/interf/glc.y" + { cout << "Compiling transitions\n";} +#line 1736 "src/interf/y.tab.cpp" + break; + + case 24: +#line 220 "src/interf/glc.y" + { strcpy(idplace,yytext); + if (tour == 1) { + if (bpn->VerifyName(idplace)) + type_error(idplace, Parser_00); + } + } +#line 1747 "src/interf/y.tab.cpp" + break; + + case 25: +#line 227 "src/interf/glc.y" + { if (tour == 1) { + Place *newp; + switch (ptype) { + case Discrete_pl : newp = new DiscretePlace(idplace); + bpn->AddPlace(currentdiscreteplace, newp); + currentdiscreteplace++; + break; + case Continuous_pl : newp = new ContinuousPlace(idplace); + bpn->AddPlace(currentcontinuousplace, newp); + currentcontinuousplace++; + break; + case Batch_pl : newp = new BatchPlace(idplace, pspeed, pdensity, plength); + bpn->AddPlace(currentbatchplace, newp); + currentbatchplace++; + break; + case Triangular_pl : newp = new TriangularBatchPlace(idplace, pspeed, pdensity, plength, pflow); + bpn->AddPlace(currenttriangularplace, newp); + currenttriangularplace++; + break; + } + } + } +#line 1774 "src/interf/y.tab.cpp" + break; + + case 29: +#line 257 "src/interf/glc.y" + { discreteplaces++; ptype = Discrete_pl; } +#line 1780 "src/interf/y.tab.cpp" + break; + + case 30: +#line 258 "src/interf/glc.y" + { continuousplaces++; ptype = Continuous_pl; } +#line 1786 "src/interf/y.tab.cpp" + break; + + case 31: +#line 259 "src/interf/glc.y" + { batchplaces++; ptype = Batch_pl; } +#line 1792 "src/interf/y.tab.cpp" + break; + + case 32: +#line 260 "src/interf/glc.y" + { triangularplaces++; ptype = Triangular_pl;} +#line 1798 "src/interf/y.tab.cpp" + break; + + case 33: +#line 268 "src/interf/glc.y" + { if ((ptype != Batch_pl) && (ptype != Triangular_pl)) { + type_error(yytext, Parser_100); + } + } +#line 1807 "src/interf/y.tab.cpp" + break; + + case 34: +#line 271 "src/interf/glc.y" + { pspeed = atof(yytext); } +#line 1813 "src/interf/y.tab.cpp" + break; + + case 35: +#line 272 "src/interf/glc.y" + { pdensity = atof(yytext); } +#line 1819 "src/interf/y.tab.cpp" + break; + + case 36: +#line 273 "src/interf/glc.y" + { plength = atof(yytext); } +#line 1825 "src/interf/y.tab.cpp" + break; + + case 39: +#line 278 "src/interf/glc.y" + { if (ptype != Triangular_pl) { + type_error(yytext, Parser_101); + } + pflow = atof(yytext); } +#line 1834 "src/interf/y.tab.cpp" + break; + + case 40: +#line 282 "src/interf/glc.y" + { if (ptype == Triangular_pl) { + yyerror(Parser_102); + } + } +#line 1843 "src/interf/y.tab.cpp" + break; + + case 42: +#line 297 "src/interf/glc.y" + { if (tour == 1){ + switch (ptype) { + case Discrete_pl : if (!is_integer){ + type_error(yytext, Parser_104); + } + else{ + bpn->SetInitialMarking((currentdiscreteplace-1), atoi(yytext)); + } + break; + case Continuous_pl : bpn->SetInitialMarking((currentcontinuousplace-1), atof(yytext)); + break; + case Batch_pl : + case Triangular_pl : type_error(yytext, Parser_103); + break; + } + } + } +#line 1865 "src/interf/y.tab.cpp" + break; + + case 44: +#line 318 "src/interf/glc.y" + { blength = atof(yytext); } +#line 1871 "src/interf/y.tab.cpp" + break; + + case 45: +#line 318 "src/interf/glc.y" + { bdensity = atof(yytext); } +#line 1877 "src/interf/y.tab.cpp" + break; + + case 46: +#line 319 "src/interf/glc.y" + { bposition = atof(yytext); } +#line 1883 "src/interf/y.tab.cpp" + break; + + case 47: +#line 320 "src/interf/glc.y" + { if (tour == 1){ + Batch *newb; + ControllableBatch *newcb; + switch (ptype) { + case Discrete_pl : type_error(yytext, Parser_104); + break; + case Continuous_pl : type_error(yytext, Parser_105); + break; + case Batch_pl : newb = new Batch(blength, bdensity, bposition); + bpn->AddBatchToInitialMarking((currentbatchplace-1), *newb); + break; + case Triangular_pl : newcb = new ControllableBatch(blength, bdensity, bposition, bspeed); + bpn->AddTriangularToInitialMarking((currenttriangularplace-1), *newcb); + break; + } + } + } +#line 1905 "src/interf/y.tab.cpp" + break; + + case 52: +#line 346 "src/interf/glc.y" + { bspeed = atof(yytext); } +#line 1911 "src/interf/y.tab.cpp" + break; + + case 53: +#line 347 "src/interf/glc.y" + { bspeed = -1;} +#line 1917 "src/interf/y.tab.cpp" + break; + + case 56: +#line 361 "src/interf/glc.y" + { if (tour == 1){ + switch (ptype) { + case Discrete_pl : if (!is_integer){ + type_error(yytext, Parser_104); + } + else{ + bpn->SetSteadyMarking((currentdiscreteplace-1), atoi(yytext)); + } + break; + case Continuous_pl : bpn->SetSteadyMarking((currentcontinuousplace-1), atof(yytext)); + break; + case Batch_pl : + case Triangular_pl : type_error(yytext, Parser_103); + break; + } + } + } +#line 1939 "src/interf/y.tab.cpp" + break; + + case 58: +#line 382 "src/interf/glc.y" + { blength = atof(yytext); } +#line 1945 "src/interf/y.tab.cpp" + break; + + case 59: +#line 382 "src/interf/glc.y" + { bdensity = atof(yytext); } +#line 1951 "src/interf/y.tab.cpp" + break; + + case 60: +#line 383 "src/interf/glc.y" + { bposition = atof(yytext); } +#line 1957 "src/interf/y.tab.cpp" + break; + + case 61: +#line 384 "src/interf/glc.y" + { if (tour == 1){ + Batch *newb; + ControllableBatch *newcb; + switch (ptype) { + case Discrete_pl : type_error(yytext, Parser_104); + break; + case Continuous_pl : type_error(yytext, Parser_105); + break; + case Batch_pl : newb = new Batch(blength, bdensity, bposition); + bpn->AddBatchToSteadyMarking((currentbatchplace-1), *newb); + break; + case Triangular_pl : newcb = new ControllableBatch(blength, bdensity, bposition, bspeed); + bpn->AddTriangularToSteadyMarking((currenttriangularplace-1), *newcb); + break; + } + } + } +#line 1979 "src/interf/y.tab.cpp" + break; + + case 66: +#line 410 "src/interf/glc.y" + { bspeed = atof(yytext); } +#line 1985 "src/interf/y.tab.cpp" + break; + + case 67: +#line 411 "src/interf/glc.y" + { bspeed = -1;} +#line 1991 "src/interf/y.tab.cpp" + break; + + case 68: +#line 419 "src/interf/glc.y" + { strcpy (idtransition, yytext); } +#line 1997 "src/interf/y.tab.cpp" + break; + + case 69: +#line 420 "src/interf/glc.y" + { if (tour == 2){ + idplacenumber = bpn->GetPlacePosition(idplace); + idtransitionnumber = bpn->GetTransitionPosition(idtransition); + if (idtransitionnumber < 0){ + type_error(idtransition, Parser_106); + } + else{ + if ((bpn->GetTransitionType(idtransition) == Discrete_tr) && !((bpn->GetPlaceType(idplace) == Discrete_pl) || (bpn->GetPlaceType(idplace) == Continuous_pl))){ + type_error(idtransition, Parser_108); + } + else{ + bpn->AddPlaceOutputArc(idplacenumber, idtransitionnumber, arcweight); + } + } + } + } +#line 2018 "src/interf/y.tab.cpp" + break; + + case 73: +#line 444 "src/interf/glc.y" + { arcweight = atof(yytext); } +#line 2024 "src/interf/y.tab.cpp" + break; + + case 75: +#line 445 "src/interf/glc.y" + {arcweight = 1.0;} +#line 2030 "src/interf/y.tab.cpp" + break; + + case 76: +#line 456 "src/interf/glc.y" + { strcpy(idtransition,yytext); + if (tour == 1) { + if (bpn->VerifyName(idtransition)) + type_error(idtransition, Parser_01); + } + } +#line 2041 "src/interf/y.tab.cpp" + break; + + case 77: +#line 463 "src/interf/glc.y" + { tsteadytime = 0.0; + tsteadyflow = 0.0; + } +#line 2049 "src/interf/y.tab.cpp" + break; + + case 78: +#line 467 "src/interf/glc.y" + { if (tour == 1) { + Transition *newt; + switch (ttype) { + case Discrete_tr : newt = new DiscreteTransition(idtransition, ttime, tsteadytime); + bpn->AddTransition(currentdiscretetransition, newt); + currentdiscretetransition++; + break; + case Continuous_tr : newt = new ContinuousTransition(idtransition, tflow, tsteadyflow); + bpn->AddTransition(currentcontinuoustransition, newt); + currentcontinuoustransition++; + break; + case Batch_tr : newt = new BatchTransition(idtransition, tflow, tsteadyflow); + bpn->AddTransition(currentbatchtransition, newt); + currentbatchtransition++; + break; + } + } + } +#line 2072 "src/interf/y.tab.cpp" + break; + + case 82: +#line 494 "src/interf/glc.y" + {discretetransitions++; ttype = Discrete_tr; } +#line 2078 "src/interf/y.tab.cpp" + break; + + case 83: +#line 495 "src/interf/glc.y" + {continuoustransitions++; ttype = Continuous_tr; } +#line 2084 "src/interf/y.tab.cpp" + break; + + case 84: +#line 496 "src/interf/glc.y" + {batchtransitions++; ttype = Batch_tr; } +#line 2090 "src/interf/y.tab.cpp" + break; + + case 85: +#line 500 "src/interf/glc.y" + { ttime = atof(yytext); } +#line 2096 "src/interf/y.tab.cpp" + break; + + case 87: +#line 501 "src/interf/glc.y" + { tflow = atof(yytext); } +#line 2102 "src/interf/y.tab.cpp" + break; + + case 91: +#line 510 "src/interf/glc.y" + { tsteadytime = atof(yytext); } +#line 2108 "src/interf/y.tab.cpp" + break; + + case 93: +#line 511 "src/interf/glc.y" + { tsteadyflow = atof(yytext); } +#line 2114 "src/interf/y.tab.cpp" + break; + + case 95: +#line 521 "src/interf/glc.y" + { strcpy (idplace, yytext); } +#line 2120 "src/interf/y.tab.cpp" + break; + + case 96: +#line 522 "src/interf/glc.y" + { if (tour == 2){ + idtransitionnumber = bpn->GetTransitionPosition(idtransition); + idplacenumber = bpn->GetPlacePosition(idplace); + if (idplacenumber < 0){ + type_error(idplace, Parser_107); + } + else{ + bpn->AddTransitionOutputArc(idtransitionnumber, idplacenumber, arcweight); + } + } + } +#line 2136 "src/interf/y.tab.cpp" + break; + + case 100: +#line 541 "src/interf/glc.y" + { arcweight = atof(yytext); } +#line 2142 "src/interf/y.tab.cpp" + break; + + case 102: +#line 542 "src/interf/glc.y" + {arcweight = 1.0;} +#line 2148 "src/interf/y.tab.cpp" + break; + + case 103: +#line 550 "src/interf/glc.y" + { cout << "Compiling controlled events\n";} +#line 2154 "src/interf/y.tab.cpp" + break; + + case 106: +#line 555 "src/interf/glc.y" + { strcpy(idcevent,yytext); } +#line 2160 "src/interf/y.tab.cpp" + break; + + case 107: +#line 555 "src/interf/glc.y" + { strcpy(idnode, yytext); } +#line 2166 "src/interf/y.tab.cpp" + break; + + case 108: +#line 556 "src/interf/glc.y" + { cevalue = atof(yytext); } +#line 2172 "src/interf/y.tab.cpp" + break; + + case 109: +#line 556 "src/interf/glc.y" + { cedate = atof(yytext); } +#line 2178 "src/interf/y.tab.cpp" + break; + + case 110: +#line 557 "src/interf/glc.y" + { + if (tour == 1){ + Node *evnode = bpn->GetNode(idnode); + ControlledEvent *ev; + if (evnode){ + switch (cetype){ + case Trans_flow_ce : if (bpn->GetTransitionPosition(idnode) == -1){ + type_error(idnode, Parser_110); + } + else{ + if (bpn->GetTransitionType(idnode) == Discrete_tr) { + type_error(idnode, Parser_113); + } + else{ + ev = new ControlledEvent(idnode, *evnode, cedate, Trans_flow_ce, cevalue, idcevent); + schedule->AddControlledEvent(*ev, Trans_flow_ce); + } + } + break; + case Place_speed_ce : if (bpn->GetPlacePosition(idnode) == -1){ + type_error(idnode, Parser_111); + } + else{ + if (bpn->GetPlaceType(idnode) != Triangular_pl) { + type_error(idnode, Parser_112); + } + else{ + ev = new ControlledEvent(idnode, *evnode, cedate, Place_speed_ce, cevalue, idcevent); + schedule->AddControlledEvent(*ev, Place_speed_ce); + } + } + break; + } + } + else{ + type_error(idnode, Parser_109); + } + } + } +#line 2222 "src/interf/y.tab.cpp" + break; + + case 114: +#line 604 "src/interf/glc.y" + { cetype = Trans_flow_ce; } +#line 2228 "src/interf/y.tab.cpp" + break; + + case 115: +#line 605 "src/interf/glc.y" + {cetype = Place_speed_ce; } +#line 2234 "src/interf/y.tab.cpp" + break; + + case 116: +#line 613 "src/interf/glc.y" + { cout << "Compiling inspection points\n";} +#line 2240 "src/interf/y.tab.cpp" + break; + + case 119: +#line 618 "src/interf/glc.y" + { strcpy(idbreakpoint,yytext); } +#line 2246 "src/interf/y.tab.cpp" + break; + + case 120: +#line 618 "src/interf/glc.y" + { bpdate = atof(yytext); } +#line 2252 "src/interf/y.tab.cpp" + break; + + case 121: +#line 618 "src/interf/glc.y" + { strcpy(idnode, yytext); } +#line 2258 "src/interf/y.tab.cpp" + break; + + case 122: +#line 619 "src/interf/glc.y" + { + if (tour == 1){ + Node *bpnode = bpn->GetNode(idnode); + Breakpoint *bp; + if ((bpnode) || (!strcmp(idnode, "places")) || (!strcmp(idnode, "transitions"))){ + bp = new Breakpoint(idnode, *bpnode, bpdate, bptype, idbreakpoint); + schedule->AddBreakpoint(*bp); + } + else{ + type_error(idnode, Parser_109); + } + } + } +#line 2276 "src/interf/y.tab.cpp" + break; + + case 126: +#line 641 "src/interf/glc.y" + { bptype = at_bp; } +#line 2282 "src/interf/y.tab.cpp" + break; + + case 127: +#line 642 "src/interf/glc.y" + { bptype = every_bp; } +#line 2288 "src/interf/y.tab.cpp" + break; + + +#line 2292 "src/interf/y.tab.cpp" + + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = YY_CAST (char *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc))); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[+*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} +#line 655 "src/interf/glc.y" + + + +void Init_Variables() +{ + yylineno = 0; + + //current place/transition + currentdiscreteplace = 0; + currentcontinuousplace = discreteplaces; + currentbatchplace = continuousplaces + discreteplaces; + currenttriangularplace = batchplaces + continuousplaces + discreteplaces; + + currentdiscretetransition = 0; + currentcontinuoustransition = discretetransitions; + currentbatchtransition = continuoustransitions + discretetransitions; +} + + +//int main(int argv, char *argc[]) +void Compile_Network(const simuleau_name bpn_level_name, const simuleau_name str_level_name) +{ + int totalplaces; + int totaltransitions; + ofstream fstr; + simuleau_name bpn_file; + + + strcpy(bpn_file, bpn_level_name); strcat(bpn_file,".bpn"); + + + //first tour: semantical analysis and number of places and transitions + tour = 0; + //counters + discreteplaces = 0; + continuousplaces = 0; + batchplaces = 0; + triangularplaces = 0; + + discretetransitions = 0; + continuoustransitions = 0; + batchtransitions = 0; + + Init_Variables(); + yyin = fopen(bpn_file, "r"); + cout << "Start model compilation\n\n"; + + cout << "First turn\n" + << "==========\n"; + cout << "Creating places and transitions structures\n"; + cout << "Creating controlled events schedule\n"; + yyparse(); + fclose(yyin); + + totalplaces = discreteplaces + continuousplaces + batchplaces + triangularplaces; + totaltransitions = discretetransitions + continuoustransitions + batchtransitions; + + if (bpn!=NULL) + delete bpn; + bpn = new BPN(totalplaces, totaltransitions); + + if (schedule!=NULL) + delete schedule; + schedule = new Schedule; + + // places initialisation + bpn->NumberOfDiscretePlaces(discreteplaces); + bpn->NumberOfContinuousPlaces(continuousplaces); + bpn->NumberOfBatchPlaces(batchplaces); + bpn->NumberOfTriangularBatchPlaces(triangularplaces); + + // transitions initialisation + bpn->NumberOfDiscreteTransitions(discretetransitions); + bpn->NumberOfContinuousTransitions(continuoustransitions); + bpn->NumberOfBatchTransitions(batchtransitions); + + + // second tour + if(!not_error){ + exit (EXIT_FAILURE); + } + + cout << "\nSecond turn\n" + << "===========\n"; + cout << "Initialising places and transitions parameters\n"; + tour++; + Init_Variables(); + yyin = fopen(bpn_file, "r"); + yyrestart(yyin); + yyparse(); + fclose(yyin); + + + // thrid tour + if(!not_error){ + exit (EXIT_FAILURE); + } + + cout << "\nThrid turn\n" + << "==========\n"; + cout << "Initialising places and transitions arcs\n"; + tour++; + bpn->AllocArcs(); + Init_Variables(); + yyin = fopen(bpn_file, "r"); + yyrestart(yyin); + yyparse(); + fclose(yyin); + bpn->AddNodeLinks(); + if(!not_error){ + exit (EXIT_FAILURE); + } + + cout << endl << bpn->GetName() << " model created\n"; + + Open_File(str_level_name, str_file, fstr); + bpn->Print(fstr); + Close_File(str_level_name, str_file, fstr); +} diff --git a/src/interf/y.tab.h b/src/interf/y.tab.h new file mode 100644 index 0000000..7421cb1 --- /dev/null +++ b/src/interf/y.tab.h @@ -0,0 +1,152 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_Y_TAB_HPP_INCLUDED +# define YY_YY_Y_TAB_HPP_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + TK_ARC = 258, + TK_BATCH = 259, + TK_CONTINUOUS = 260, + TK_CONTROLLED = 261, + TK_DESCRIPTION = 262, + TK_DISCRETE = 263, + TK_EVENTS = 264, + TK_FLOW = 265, + TK_FUNCTION = 266, + TK_INITIAL = 267, + TK_INSPECTION = 268, + TK_LENGTH = 269, + TK_MARKING = 270, + TK_MODEL = 271, + TK_NETWORK = 272, + TK_OUTPUT = 273, + TK_PLACE = 274, + TK_PLACES = 275, + TK_SPEED = 276, + TK_STEADY = 277, + TK_TIME = 278, + TK_TIMING = 279, + TK_TRANSITION = 280, + TK_TRANSITIONS = 281, + TK_TRIANGULAR = 282, + TK_UNITY = 283, + TK_ID = 284, + TK_INTEGER = 285, + TK_REAL = 286, + TK_EXPONENT = 287, + TK_AT = 288, + TK_EVERY = 289, + TK_LEFT_BRACKET = 290, + TK_RIGHT_BRACKET = 291, + TK_PL_TR = 292, + TK_ALL = 293, + TK_LEFT_PARENTHESIS = 294, + TK_RIGHT_PARENTHESIS = 295, + TK_LEFT_SQUARE_BRACKET = 296, + TK_RIGHT_SQUARE_BRACKET = 297, + TK_SEMICOLON = 298, + TK_COMMA = 299, + TK_ATTRIB = 300, + TK_COLON = 301 + }; +#endif +/* Tokens. */ +#define TK_ARC 258 +#define TK_BATCH 259 +#define TK_CONTINUOUS 260 +#define TK_CONTROLLED 261 +#define TK_DESCRIPTION 262 +#define TK_DISCRETE 263 +#define TK_EVENTS 264 +#define TK_FLOW 265 +#define TK_FUNCTION 266 +#define TK_INITIAL 267 +#define TK_INSPECTION 268 +#define TK_LENGTH 269 +#define TK_MARKING 270 +#define TK_MODEL 271 +#define TK_NETWORK 272 +#define TK_OUTPUT 273 +#define TK_PLACE 274 +#define TK_PLACES 275 +#define TK_SPEED 276 +#define TK_STEADY 277 +#define TK_TIME 278 +#define TK_TIMING 279 +#define TK_TRANSITION 280 +#define TK_TRANSITIONS 281 +#define TK_TRIANGULAR 282 +#define TK_UNITY 283 +#define TK_ID 284 +#define TK_INTEGER 285 +#define TK_REAL 286 +#define TK_EXPONENT 287 +#define TK_AT 288 +#define TK_EVERY 289 +#define TK_LEFT_BRACKET 290 +#define TK_RIGHT_BRACKET 291 +#define TK_PL_TR 292 +#define TK_ALL 293 +#define TK_LEFT_PARENTHESIS 294 +#define TK_RIGHT_PARENTHESIS 295 +#define TK_LEFT_SQUARE_BRACKET 296 +#define TK_RIGHT_SQUARE_BRACKET 297 +#define TK_SEMICOLON 298 +#define TK_COMMA 299 +#define TK_ATTRIB 300 +#define TK_COLON 301 + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + +int yyparse (void); + +#endif /* !YY_YY_Y_TAB_HPP_INCLUDED */ diff --git a/src/interf/y.tab.hpp b/src/interf/y.tab.hpp new file mode 100644 index 0000000..0acf8e5 --- /dev/null +++ b/src/interf/y.tab.hpp @@ -0,0 +1,156 @@ +/* A Bison parser, made by GNU Bison 3.5.1. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + +#ifndef YY_YY_SRC_INTERF_Y_TAB_HPP_INCLUDED +# define YY_YY_SRC_INTERF_Y_TAB_HPP_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + TK_ARC = 258, + TK_BATCH = 259, + TK_CONTINUOUS = 260, + TK_CONTROLLED = 261, + TK_DESCRIPTION = 262, + TK_DISCRETE = 263, + TK_EVENTS = 264, + TK_FLOW = 265, + TK_FUNCTION = 266, + TK_INITIAL = 267, + TK_INSPECTION = 268, + TK_LENGTH = 269, + TK_MARKING = 270, + TK_MODEL = 271, + TK_NETWORK = 272, + TK_OUTPUT = 273, + TK_PLACE = 274, + TK_PLACES = 275, + TK_SPEED = 276, + TK_STEADY = 277, + TK_TIME = 278, + TK_TIMING = 279, + TK_TRANSITION = 280, + TK_TRANSITIONS = 281, + TK_TRIANGULAR = 282, + TK_UNITY = 283, + TK_ID = 284, + TK_INTEGER = 285, + TK_REAL = 286, + TK_EXPONENT = 287, + TK_AT = 288, + TK_EVERY = 289, + TK_LEFT_BRACKET = 290, + TK_RIGHT_BRACKET = 291, + TK_PL_TR = 292, + TK_ALL = 293, + TK_LEFT_PARENTHESIS = 294, + TK_RIGHT_PARENTHESIS = 295, + TK_LEFT_SQUARE_BRACKET = 296, + TK_RIGHT_SQUARE_BRACKET = 297, + TK_SEMICOLON = 298, + TK_COMMA = 299, + TK_ATTRIB = 300, + TK_COLON = 301 + }; +#endif +/* Tokens. */ +#define TK_ARC 258 +#define TK_BATCH 259 +#define TK_CONTINUOUS 260 +#define TK_CONTROLLED 261 +#define TK_DESCRIPTION 262 +#define TK_DISCRETE 263 +#define TK_EVENTS 264 +#define TK_FLOW 265 +#define TK_FUNCTION 266 +#define TK_INITIAL 267 +#define TK_INSPECTION 268 +#define TK_LENGTH 269 +#define TK_MARKING 270 +#define TK_MODEL 271 +#define TK_NETWORK 272 +#define TK_OUTPUT 273 +#define TK_PLACE 274 +#define TK_PLACES 275 +#define TK_SPEED 276 +#define TK_STEADY 277 +#define TK_TIME 278 +#define TK_TIMING 279 +#define TK_TRANSITION 280 +#define TK_TRANSITIONS 281 +#define TK_TRIANGULAR 282 +#define TK_UNITY 283 +#define TK_ID 284 +#define TK_INTEGER 285 +#define TK_REAL 286 +#define TK_EXPONENT 287 +#define TK_AT 288 +#define TK_EVERY 289 +#define TK_LEFT_BRACKET 290 +#define TK_RIGHT_BRACKET 291 +#define TK_PL_TR 292 +#define TK_ALL 293 +#define TK_LEFT_PARENTHESIS 294 +#define TK_RIGHT_PARENTHESIS 295 +#define TK_LEFT_SQUARE_BRACKET 296 +#define TK_RIGHT_SQUARE_BRACKET 297 +#define TK_SEMICOLON 298 +#define TK_COMMA 299 +#define TK_ATTRIB 300 +#define TK_COLON 301 + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + +int yyparse (void); + +#endif /* !YY_YY_SRC_INTERF_Y_TAB_HPP_INCLUDED */ diff --git a/src/simul/breakpoint.cpp b/src/simul/breakpoint.cpp new file mode 100644 index 0000000..2e56795 --- /dev/null +++ b/src/simul/breakpoint.cpp @@ -0,0 +1,170 @@ +//====================================================================================// +// // +// Breakpoint class // +// // +//====================================================================================// +// This File: breakpoint.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 27/septembre/17 by: Leonardo.Brenner@lsis.org // +// Last Change: 27/septembre/17 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Breakpoint class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Breakpoint::Breakpoint() +{ + //ctor +} + +//------------------------------------------------------------------------------ +// Initialized constructor +//------------------------------------------------------------------------------ +Breakpoint::Breakpoint(simuleau_name _idnode, Node& _node, double _date_frequency, breakpoint_type _type, simuleau_name _name) +{ + node = &_node; + strcpy(idnode, _idnode); + strcpy(name, _name); + type = _type; + + if (type == at_bp) { + date = _date_frequency; + } + else{ + date = 0.0; + frequency = _date_frequency; + } +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Breakpoint::~Breakpoint() +{ + //dtor +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void Breakpoint::Copy(const Breakpoint &_breakpoint) +{ + date = _breakpoint.date; + node = _breakpoint.node; + type = _breakpoint.type; + frequency = _breakpoint.frequency; + + strcpy(name, _breakpoint.name); + strcpy(idnode, _breakpoint.idnode); +} + +//------------------------------------------------------------------------------ +// It returns breakpoint name +//------------------------------------------------------------------------------ +char* Breakpoint::GetName() +{ + return (name); +} + +//------------------------------------------------------------------------------ +// It returns breakpoint node id +// places represents all places and transitions represents all transitions +//------------------------------------------------------------------------------ +char* Breakpoint::GetNodeId() +{ + return (idnode); +} + +//------------------------------------------------------------------------------ +// Return the node related to the breakpoint +//------------------------------------------------------------------------------ +Node* Breakpoint::GetNode(BPN *_bpn) +{ + node = _bpn->GetNode(idnode); + return (node); +} + +//------------------------------------------------------------------------------ +// Return the breakpoint date +//------------------------------------------------------------------------------ +double Breakpoint::GetDate(double currentdate) +{ + + if (type == at_bp) + return (date); + else{ + date = (((int) currentdate/frequency) + 1) * frequency; + return (date); + } +} + +//------------------------------------------------------------------------------ +// Return the breakpoint type +// at_bp for pontual breakpoint +// every_bp for recurent breakpoint +//------------------------------------------------------------------------------ +breakpoint_type Breakpoint::GetType() +{ + return (type); +} + +//------------------------------------------------------------------------------ +// Return the textual breakpoint description +//------------------------------------------------------------------------------ +char* Breakpoint::GetDescription() +{ + switch (type) + { + case at_bp: return("Breakpoint at a specific date"); + case every_bp: return("Recurent breakpoint"); + } +} + + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Breakpoint::Print(ostream &fout) +{ + fout << "Breakpoint Name: " << name << endl; + fout << "Node Name: " << idnode << endl; + if (type == at_bp){ + fout << "Date: " << date << endl; + } + else{ + fout << "Frequency: " << frequency << endl; + } + fout << "Type: " << GetDescription() << endl; +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Breakpoint::PrintPlaceTransition(BPN *_bpn, ostream &fout) +{ + Node *bpnode; + + fout << "Breakpoint Name: " << name << endl; + + if (!strcmp(idnode,"places")){ // print all places + _bpn->WritePlaces(fout); + return; + } + + if (!strcmp(idnode,"transitions")){ // print all transitions + _bpn->WriteFlows(fout); + return; + } + + //print just one place or transition + bpnode = GetNode(_bpn); + bpnode->Print(fout); +} diff --git a/src/simul/breakpoint.h b/src/simul/breakpoint.h new file mode 100644 index 0000000..8b8da45 --- /dev/null +++ b/src/simul/breakpoint.h @@ -0,0 +1,54 @@ +//====================================================================================// +// // +// Breakpoint class // +// // +//====================================================================================// +// This File: breakpoint.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 27/septembre/17 by: Leonardo.Brenner@lsis.org // +// Last Change: 27/septembre/17 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef BREAKPOINT_H +#define BREAKPOINT_H + +//====================================================================================// +// Generic breakpoint class // +//====================================================================================// +// Breakpoint class implements breakpoint to inspect the state of places and // +// transitions at date where it have no events. // +//====================================================================================// +class Breakpoint +{ + public: + Breakpoint(); + Breakpoint(simuleau_name _idnode, Node& _node, double _date_frequency, breakpoint_type _type, simuleau_name _name); + ~Breakpoint(); + + void Copy(const Breakpoint &_breakpoint); + + //output functions + char* GetName(); + char* GetNodeId(); + Node* GetNode(BPN *_bpn); + double GetDate(double currentdate); + breakpoint_type GetType(); + char* GetDescription(); + + // print functions + void Print(ostream &fout); + void PrintPlaceTransition(BPN *_bpn, ostream &fout); + + protected: + Node *node; + simuleau_name idnode; + simuleau_name name; + double date; + double frequency; + breakpoint_type type; + + private: +}; + + +#endif // BREAKPOINT_H diff --git a/src/simul/event.cpp b/src/simul/event.cpp new file mode 100644 index 0000000..945d9da --- /dev/null +++ b/src/simul/event.cpp @@ -0,0 +1,222 @@ +//====================================================================================// +// // +// Event class // +// // +//====================================================================================// +// This File: event.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 07/may/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 07/may/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Event class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Event::Event() +{ + //ctor +} + +//------------------------------------------------------------------------------ +// Initialized constructor +//------------------------------------------------------------------------------ +Event::Event(Node &_node, double _date, ev_type _type) +{ + node = &_node; + date = _date; + type = _type; +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Event::~Event() +{ + //dtor +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void Event::Copy(const Event &_event) +{ + date = _event.date; + node = _event.node; + type = _event.type; +} + +//------------------------------------------------------------------------------ +// Return the event date +//------------------------------------------------------------------------------ +double Event::GetDate() +{ + return (date); +} + +//------------------------------------------------------------------------------ +// Return the event type +//------------------------------------------------------------------------------ +ev_type Event::GetType() +{ + return (type); +} + +//------------------------------------------------------------------------------ +// Return the node related to the event +//------------------------------------------------------------------------------ +Node* Event::GetNode() +{ + return (node); +} + +//------------------------------------------------------------------------------ +// Return the textual event description +//------------------------------------------------------------------------------ +char* Event::GetDescription() +{ + switch (type) + { + case Discr_trans_fires: return("Discrete transition is fired"); + case Cont_place_empty: return("Continuous place becomes empty"); + case Discr_trans_enabled: return("Discrete transition becomes enable"); + case Becomes_output_batch:return("Batch becomes an output batch"); + case Destr_output_batch: return("Destruction of an output batch"); + case Batch_becomes_dense: return("Batch becomes dense"); + case Two_batches_meet: return("Two batches meet"); + case Batch_meets_output_batch: return("A batch meets an output batch"); + case Output_batch_decongestion: return("Decongestion of the output batch"); + case Batch_decongestion: return("Decongestion of a batch in contact ahead"); + case Batch_becomes_free: return("Full decongestion of a batch alone"); + case Place_steady_quan: return("Place reaches steady marking quantity"); + case Remaining_becomes_freesteadyquan: return("Remaining quantity passed by an input transition becomes free steady quantity"); + } +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Event::Print(ostream &fout) +{ + fout << "Date: " << date << endl; + node->Print(fout); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Methods of the Controlled Event class +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +ControlledEvent::ControlledEvent() +{ + +} + +//------------------------------------------------------------------------------ +// Initialized constructor +//------------------------------------------------------------------------------ +ControlledEvent::ControlledEvent(Node& _node, double _date, ev_type _type, double _value, simuleau_name _name):Event(_node, _date, _type) +{ + value = _value; + strcpy(name, _name); +} + +//------------------------------------------------------------------------------ +// Initialized constructor +//------------------------------------------------------------------------------ +ControlledEvent::ControlledEvent(simuleau_name _idnode, Node& _node, double _date, ev_type _type, double _value, simuleau_name _name):Event(_node, _date, _type) +{ + value = _value; + strcpy(name, _name); + strcpy(idnode, _idnode); +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +ControlledEvent::~ControlledEvent() +{ + +} + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void ControlledEvent::Copy(const ControlledEvent &_event) +{ + date = _event.date; + node = _event.node; + type = _event.type; + + strcpy(name, _event.name); + strcpy(idnode, _event.idnode); + value = _event.value; +} + +//------------------------------------------------------------------------------ +// It returns controlled event name +//------------------------------------------------------------------------------ +char* ControlledEvent::GetName() +{ + return (name); +} + +//------------------------------------------------------------------------------ +// It returns controlled event value +//------------------------------------------------------------------------------ +double ControlledEvent::GetValue() +{ + return (value); +} + +//------------------------------------------------------------------------------ +// Return the node related to the event +//------------------------------------------------------------------------------ +Node* ControlledEvent::GetNode(BPN *_bpn) +{ + node = _bpn->GetNode(idnode); + return (node); +} + +//------------------------------------------------------------------------------ +// It returns controlled event node id +//------------------------------------------------------------------------------ +char* ControlledEvent::GetNodeId() +{ + return (idnode); +} + +//------------------------------------------------------------------------------ +// Return the textual event description +//------------------------------------------------------------------------------ +char* ControlledEvent::GetDescription() +{ + switch (type) + { + case Trans_flow_ce: return("Transition maximum flow changes"); + case Place_speed_ce: return("Place maximum speed changes"); + } +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void ControlledEvent::Print(ostream &fout) +{ + fout << "Event Name: " << name << endl; + fout << "Node Name: " << idnode << endl; + fout << "Date: " << date << endl; + fout << "Type: " << GetDescription() << endl; + fout << "Value: " << value << endl; +} diff --git a/src/simul/event.h b/src/simul/event.h new file mode 100644 index 0000000..317378a --- /dev/null +++ b/src/simul/event.h @@ -0,0 +1,89 @@ +//====================================================================================// +// // +// Event class // +// // +//====================================================================================// +// This File: event.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 07/may/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 07/may/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef EVENT_H +#define EVENT_H + +//====================================================================================// +// Generic event class // +//====================================================================================// +// Event class implements a generic event that will be used to implement all types // +// of events in the schedule class. // +//====================================================================================// +class Event +{ + public: + Event(); + Event(Node &_node, double _date, ev_type _type); + virtual ~Event(); + + void Copy(const Event &_event); + + //output functions + double GetDate(); + ev_type GetType(); + Node* GetNode(); + virtual char* GetDescription(); + + // print functions + virtual void Print(ostream &fout); + + protected: + Node *node; + double date; + ev_type type; + + private: +}; + + + +//====================================================================================// +// Controlled event class // +//====================================================================================// +// Controlled event class implements the storage of external controlled events // +// readed from the input bpn file these events modify the flow or speed of transitions// +// or places. // +//====================================================================================// +class ControlledEvent : public Event +{ + public: + ControlledEvent(); + ControlledEvent(Node &_node, double _date, ev_type _type, double _value, simuleau_name _name); + ControlledEvent(simuleau_name _idnode, Node& _node, double _date, ev_type _type, double _value, simuleau_name _name); + + virtual ~ControlledEvent(); + + void Copy(const ControlledEvent &_event); + + //output functions + char* GetName(); + double GetValue(); + Node* GetNode(BPN *_bpn); + char* GetNodeId(); + char* GetDescription(); + + // print functions + void Print(ostream &fout); + + protected: + double value; + simuleau_name idnode; + simuleau_name name; + + private: +}; + + + + + +#endif // EVENT_H diff --git a/src/simul/schedule.cpp b/src/simul/schedule.cpp new file mode 100644 index 0000000..146d29b --- /dev/null +++ b/src/simul/schedule.cpp @@ -0,0 +1,967 @@ +//====================================================================================// +// // +// Schedule class // +// // +//====================================================================================// +// This File: schedule.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 08/may/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 24/jan/20 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Schedule::Schedule() +{ + dtf = new list<Event>; // Discrete Transition is Fired + dtf->clear(); + cpe = new list<Event>; // Continuous Place becomes Empty + cpe->clear(); + dte = new list<Event>; // Discrete Transition becomes Enable + dte->clear(); + bob = new list<Event>; // Batch becomes an Output Batch + bob->clear(); + dob = new list<Event>; // Destruction of an Output Batch + dob->clear(); + bbd = new list<Event>; // Batch Becomes Dense + bbd->clear(); + tbm = new list<Event>; // Two Batches Meet + tbm->clear(); + bmob = new list<Event>; // A batch meets an output batch + bmob->clear(); + obd = new list<Event>; // Decongestion of the output batch + obd->clear(); + bd = new list<Event>; // Decongestion of a batch in contact head + bd->clear(); + bbf = new list<Event>; // Full decongestion of a batch alone + bbf->clear(); + psq = new list<Event>; // Place reaches Steady marking Quantity + psq->clear(); + rbf = new list<Event>; // Remaining quantity entered by an input transition becomes equal to free steady marking quantity. + rbf->clear(); + + + tfce = new list<ControlledEvent>; // Transition maximum Flow changes + tfce->clear(); + psce = new list<ControlledEvent>; // Place maximum Speed changes + psce->clear(); + + breakpoint = new list<Breakpoint>; + breakpoint->clear(); + + nextevents = new list<Event>; + nextevents->clear(); + + nextcontrolledevents = new list<ControlledEvent>; + nextcontrolledevents->clear(); + + nextbreakpoints = new list<Breakpoint>; + nextbreakpoints->clear(); +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Schedule::~Schedule() +{ + if (dtf) + delete dtf; + if (cpe) + delete cpe; + if (dte) + delete dte; + if (bob) + delete bob; + if (dob) + delete dob; + if (bbd) + delete bbd; + if (tbm) + delete tbm; + if (bmob) + delete bmob; + if (obd) + delete obd; + if (bd) + delete bd; + if (bbd) + delete bbf; + if (psq) + delete psq; + if (rbf) + delete rbf; + + + if (tfce) + delete tfce; + if (psce) + delete psce; + + if (breakpoint) + delete breakpoint; + + if (nextevents) + delete nextevents; + + if (nextcontrolledevents) + delete nextcontrolledevents; + + if (nextbreakpoints) + delete nextbreakpoints; +} + + +//------------------------------------------------------------------------------ +// Copy +//------------------------------------------------------------------------------ +void Schedule::Copy(const Schedule *_schedule) +{ + dtf->clear(); + for (list<Event>::iterator it=_schedule->dtf->begin(); it!=_schedule->dtf->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + dtf->push_back(*newevent); + } + + cpe->clear(); + for (list<Event>::iterator it=_schedule->cpe->begin(); it!=_schedule->cpe->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + cpe->push_back(*newevent); + } + + dte->clear(); + for (list<Event>::iterator it=_schedule->dte->begin(); it!=_schedule->dte->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + dte->push_back(*newevent); + } + + bob->clear(); + for (list<Event>::iterator it=_schedule->bob->begin(); it!=_schedule->bob->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + bob->push_back(*newevent); + } + + dob->clear(); + for (list<Event>::iterator it=_schedule->dob->begin(); it!=_schedule->dob->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + dob->push_back(*newevent); + } + + bbd->clear(); + for (list<Event>::iterator it=_schedule->bbd->begin(); it!=_schedule->bbd->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + bbd->push_back(*newevent); + } + + tbm->clear(); + for (list<Event>::iterator it=_schedule->tbm->begin(); it!=_schedule->tbm->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + tbm->push_back(*newevent); + } + + bmob->clear(); + for (list<Event>::iterator it=_schedule->bmob->begin(); it!=_schedule->bmob->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + bmob->push_back(*newevent); + } + + obd->clear(); + for (list<Event>::iterator it=_schedule->obd->begin(); it!=_schedule->obd->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + obd->push_back(*newevent); + } + + bd->clear(); + for (list<Event>::iterator it=_schedule->bd->begin(); it!=_schedule->bd->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + bd->push_back(*newevent); + } + + bbf->clear(); + for (list<Event>::iterator it=_schedule->bbf->begin(); it!=_schedule->bbf->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + bbf->push_back(*newevent); + } + + psq->clear(); + for (list<Event>::iterator it=_schedule->psq->begin(); it!=_schedule->psq->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + psq->push_back(*newevent); + } + + rbf->clear(); + for (list<Event>::iterator it=_schedule->rbf->begin(); it!=_schedule->rbf->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + rbf->push_back(*newevent); + } + + + + + tfce->clear(); + for (list<ControlledEvent>::iterator it=_schedule->tfce->begin(); it!=_schedule->tfce->end(); ++it) { + ControlledEvent *newevent = new ControlledEvent; + newevent->Copy(*it); + tfce->push_back(*newevent); + } + + psce->clear(); + for (list<ControlledEvent>::iterator it=_schedule->psce->begin(); it!=_schedule->psce->end(); ++it) { + ControlledEvent *newevent = new ControlledEvent; + newevent->Copy(*it); + psce->push_back(*newevent); + } + + breakpoint->clear(); + for (list<Breakpoint>::iterator it=_schedule->breakpoint->begin(); it!=_schedule->breakpoint->end(); ++it) { + Breakpoint *newbreakpoint = new Breakpoint; + newbreakpoint->Copy(*it); + breakpoint->push_back(*newbreakpoint); + } + + nextevents->clear(); + for (list<Event>::iterator it=_schedule->nextevents->begin(); it!=_schedule->nextevents->end(); ++it) { + Event *newevent = new Event; + newevent->Copy(*it); + nextevents->push_back(*newevent); + } + + nextcontrolledevents->clear(); + for (list<ControlledEvent>::iterator it=_schedule->nextcontrolledevents->begin(); it!=_schedule->nextcontrolledevents->end(); ++it) { + ControlledEvent *newevent = new ControlledEvent; + newevent->Copy(*it); + nextcontrolledevents->push_back(*newevent); + } + + nextbreakpoints->clear(); + for (list<Breakpoint>::iterator it=_schedule->nextbreakpoints->begin(); it!=_schedule->nextbreakpoints->end(); ++it) { + Breakpoint *newbreakpoint = new Breakpoint; + newbreakpoint->Copy(*it); + nextbreakpoints->push_back(*newbreakpoint); + } +} + +//------------------------------------------------------------------------------ +// Add a new event +//------------------------------------------------------------------------------ +void Schedule::AddEvent(Event& e, ev_type type) +{ + switch(type){ + case Discr_trans_fires: dtf->push_back(e); + break; + case Cont_place_empty: cpe->push_back(e); + break; + case Discr_trans_enabled: dte->push_back(e); + break; + case Becomes_output_batch:bob->push_back(e); + break; + case Destr_output_batch: dob->push_back(e); + break; + case Batch_becomes_dense: bbd->push_back(e); + break; + case Two_batches_meet: tbm->push_back(e); + break; + case Batch_meets_output_batch: bmob->push_back(e); + break; + case Output_batch_decongestion: obd->push_back(e); + break; + case Batch_decongestion: bd->push_back(e); + break; + case Batch_becomes_free: bbf->push_back(e); + break; + case Place_steady_quan: psq->push_back(e); // place reaches steady marking quantity + break; + case Remaining_becomes_freesteadyquan: rbf->push_back(e); //Remaining marking quantity entered by an input transition becomes free steady quantity. + break; + } +} + +//------------------------------------------------------------------------------ +// Add a new controlled external event from the input bpn file +//------------------------------------------------------------------------------ +void Schedule::AddControlledEvent(ControlledEvent& ce, ev_type type) +{ + switch(type){ + case Trans_flow_ce: tfce->push_back(ce); + break; + case Place_speed_ce: psce->push_back(ce); + break; + } +} + +//------------------------------------------------------------------------------ +// Add a new breakpoint from the input bpn file +//------------------------------------------------------------------------------ +void Schedule::AddBreakpoint(Breakpoint& bp) +{ + breakpoint->push_back(bp); +} + +//------------------------------------------------------------------------------ +// Add a new controlled external event from the input bpn file +//------------------------------------------------------------------------------ +char* Schedule::GetEventDescription(ev_type type) +{ + switch (type) + { + case Discr_trans_fires: return("Discrete transition is fired"); + case Cont_place_empty: return("Continuous place becomes empty"); + case Discr_trans_enabled: return("Discrete transition becomes enable"); + case Becomes_output_batch:return("Batch becomes an output batch"); + case Destr_output_batch: return("Destruction of an output batch"); + case Batch_becomes_dense: return("Batch becomes dense"); + case Two_batches_meet: return("Two batches meet"); + case Batch_meets_output_batch: return("A batch meets an output batch"); + case Output_batch_decongestion: return("Decongestion of the output batch"); + case Batch_decongestion: return("Decongestion of a batch in contact ahead"); + case Batch_becomes_free: return("Full decongestion of a batch alone"); + case Place_steady_quan: return("Place reaches steady marking quantity"); + case Trans_flow_ce: return("Transition maximum flow changes"); + case Place_speed_ce: return("Place maximum speed changes"); + case Remaining_becomes_freesteadyquan: return("Remaining quantity passed by an input transition becomes free steady quantity"); + } +} + +//------------------------------------------------------------------------------ +// Add a new controlled external event from the input bpn file +//------------------------------------------------------------------------------ +char* Schedule::GetBreakpointDescription(breakpoint_type type) +{ + switch (type) + { + case at_bp: return("Breakpoint at a specific date"); + case every_bp: return("Recurent breakpoint"); + } +} + +//------------------------------------------------------------------------------ +// Returns true if the schedule doesn't have more events to proceed +//------------------------------------------------------------------------------ +int Schedule::IsEmpty() +{ + if (nextevents->empty() && nextcontrolledevents->empty() && nextbreakpoints->empty()) + return (1); + else + return (0); +} + +//------------------------------------------------------------------------------ +// This fonction delete all controlled event that are before the current date +//------------------------------------------------------------------------------ +void Schedule::Clean(list<ControlledEvent> *cevl, double _currentdate) +{ + int numerofcontrolledevents = cevl->size(); + + for (int i=0; i<numerofcontrolledevents; i++){ + ControlledEvent *ce = new ControlledEvent; + *ce = cevl->front(); + cevl->pop_front(); + double eventdate = ce->GetDate(); + + if (eventdate <= _currentdate){ + continue; + } + else{ + cevl->push_back(*ce); + } + } +} + +//------------------------------------------------------------------------------ +// This fonction delete all controlled event +//------------------------------------------------------------------------------ +void Schedule::CleanAll() +{ + int numerofcontrolledevents = tfce->size(); + + for (int i=0; i<numerofcontrolledevents; i++){ + ControlledEvent *ce = new ControlledEvent; + *ce = tfce->front(); + tfce->pop_front(); + } + + numerofcontrolledevents = psce->size(); + + for (int i=0; i<numerofcontrolledevents; i++){ + ControlledEvent *ce = new ControlledEvent; + *ce = tfce->front(); + psce->pop_front(); + } +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Schedule::PrintEvents(ostream &fout) +{ + cout << "Discrete transition is fired: " << dtf->size() << endl; + for (list<Event>::iterator it=dtf->begin(); it!=dtf->end(); ++it) { + it->Print(fout); + } + + cout << "\nContinuous place becomes empty: " << cpe->size() << endl; + for (list<Event>::iterator it=cpe->begin(); it!=cpe->end(); ++it) { + it->Print(fout); + } + + cout << "\nDiscrete transition becomes enable: " << dte->size() << endl; + for (list<Event>::iterator it=dte->begin(); it!=dte->end(); ++it) { + it->Print(fout); + } + + cout << "\nBatch becomes an output batch: " << bob->size() << endl; + for (list<Event>::iterator it=bob->begin(); it!=bob->end(); ++it) { + it->Print(fout); + } + + cout << "\nDestruction of an output batch: " << dob->size() << endl; + for (list<Event>::iterator it=dob->begin(); it!=dob->end(); ++it) { + it->Print(fout); + } + + cout << "\nBatch becomes dense: " << bbd->size() << endl; + for (list<Event>::iterator it=bbd->begin(); it!=bbd->end(); ++it) { + it->Print(fout); + } + + cout << "\nTwo batches meet: " << tbm->size() << endl; + for (list<Event>::iterator it=tbm->begin(); it!=tbm->end(); ++it) { + it->Print(fout); + } + + cout << "\nA batch meets an output batch: " << bmob->size() << endl; + for (list<Event>::iterator it=bmob->begin(); it!=bmob->end(); ++it) { + it->Print(fout); + } + + cout << "\nDecongestion of the output batch: " << obd->size() << endl; + for (list<Event>::iterator it=obd->begin(); it!=obd->end(); ++it) { + it->Print(fout); + } + + cout << "\nDecongestion of a batch in contact ahead: " << bd->size() << endl; + for (list<Event>::iterator it=bd->begin(); it!=bd->end(); ++it) { + it->Print(fout); + } + + cout << "\nFull decongestion of a batch alone: " << bbf->size() << endl; + for (list<Event>::iterator it=bbf->begin(); it!=bbf->end(); ++it) { + it->Print(fout); + } + + cout << "\nPlace reaches steady marking quantity: " << psq->size() << endl; + for (list<Event>::iterator it=psq->begin(); it!=psq->end(); ++it) { + it->Print(fout); + } + + cout << "\nRemain quantity passed by an input transition becomes free steady quantity : " << rbf->size() << endl; + for (list<Event>::iterator it=rbf->begin(); it!=rbf->end(); ++it) { + it->Print(fout); + } + +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Schedule::PrintCE(ostream &fout) +{ + cout << "Transition maximum flow changes: " << tfce->size() << endl; + for (list<ControlledEvent>::iterator it=tfce->begin(); it!=tfce->end(); ++it) { + it->Print(fout); + } + cout << endl; + + cout << "Place maximum speed changes: " << psce->size() << endl; + for (list<ControlledEvent>::iterator it=psce->begin(); it!=psce->end(); ++it) { + it->Print(fout); + } +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Schedule::PrintBP(ostream &fout) +{ + for (list<Breakpoint>::iterator it=breakpoint->begin(); it!=breakpoint->end(); ++it) { + it->Print(fout); + } +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Schedule::Print(ostream &fout) +{ + fout << "Schedule" << endl; + fout << "========" << endl; + + fout << "Events\n" + << "------" << endl; + PrintEvents(fout); + + fout << "\nControlled events\n" + << "-----------------" << endl; + PrintCE(fout); + + fout << "\nBreakpoints\n" + << "-----------" << endl; + PrintBP(fout); +} + +//------------------------------------------------------------------------------ +// It writes the events list in the file +//------------------------------------------------------------------------------ +void Schedule::WriteEvents(ofstream &fout) +{ + if (!dtf->empty()){ + fout << "\bDiscrete transition is fired: " << dtf->size() << endl; + for (list<Event>::iterator it=dtf->begin(); it!=dtf->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!cpe->empty()){ + fout << "\nContinuous place becomes empty: " << cpe->size() << endl; + for (list<Event>::iterator it=cpe->begin(); it!=cpe->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!dte->empty()){ + fout << "\nDiscrete transition becomes enable: " << dte->size() << endl; + for (list<Event>::iterator it=dte->begin(); it!=dte->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!bob->empty()){ + fout << "\nBatch becomes an output batch: " << bob->size() << endl; + for (list<Event>::iterator it=bob->begin(); it!=bob->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!dob->empty()){ + fout << "\nDestruction of an output batch: " << dob->size() << endl; + for (list<Event>::iterator it=dob->begin(); it!=dob->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!bbd->empty()){ + fout << "\nBatch becomes dense: " << bbd->size() << endl; + for (list<Event>::iterator it=bbd->begin(); it!=bbd->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!tbm->empty()){ + fout << "\nTwo batches meet: " << tbm->size() << endl; + for (list<Event>::iterator it=tbm->begin(); it!=tbm->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!bmob->empty()){ + fout << "\nA batch meets an output batch: " << bmob->size() << endl; + for (list<Event>::iterator it=bmob->begin(); it!=bmob->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!obd->empty()){ + fout << "\nDecongestion of the output batch: " << obd->size() << endl; + for (list<Event>::iterator it=obd->begin(); it!=obd->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!bd->empty()){ + fout << "\nDecongestion of a batch in contact ahead: " << bd->size() << endl; + for (list<Event>::iterator it=bd->begin(); it!=bd->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!bbf->empty()){ + fout << "\nFull decongestion of a batch alone: " << bbf->size() << endl; + for (list<Event>::iterator it=bbf->begin(); it!=bbf->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + } + } + + if (!psq->empty()){ + fout << "\nPlace reaches steady marking quantity: " << psq->size() << endl; + for (list<Event>::iterator it=psq->begin(); it!=psq->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + // it->Print(fout); + } + } + + if (!rbf->empty()){ + fout << "\nRemain quantity passed by an input transition becomes free steady quantity: " << rbf->size() << endl; + for (list<Event>::iterator it=rbf->begin(); it!=rbf->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNode())->GetName() << endl; + // it->Print(fout); + } + } + +} + +//------------------------------------------------------------------------------ +// It writes the controlled events list in the file +//------------------------------------------------------------------------------ +void Schedule::WriteCE(ofstream &fout) +{ + Clean(tfce, simulation->stime->GetCurrentDate()); + Clean(psce, simulation->stime->GetCurrentDate()); + + if (!tfce->empty() || !psce->empty()) + fout << endl << "Controlled Events" << endl; + + + if (!tfce->empty()){ + fout << "\nTransition maximum flow changes: " << tfce->size() << endl; + for (list<ControlledEvent>::iterator it=tfce->begin(); it!=tfce->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNodeId()) << "\t name " << it->GetName() << endl; + } + } + + if (!psce->empty()){ + fout << "\nPlace maximum speed changes: " << psce->size() << endl; + for (list<ControlledEvent>::iterator it=psce->begin(); it!=psce->end(); ++it) { + fout << "Date " << it->GetDate() << "\t node " << (it->GetNodeId()) << "\t name " << it->GetName() << endl; + } + } + +} + +//------------------------------------------------------------------------------ +// It writes the breakpoint list in the file +//------------------------------------------------------------------------------ +void Schedule::WriteBP(ofstream &fout) +{ + if (!breakpoint->empty()){ + fout << "\nBreakpoints: " << breakpoint->size() << endl; + for (list<Breakpoint>::iterator it=breakpoint->begin(); it!=breakpoint->end(); ++it) { + fout << "Date " << it->GetDate(simulation->stime->GetCurrentDate()) << "\t node " << (it->GetNodeId()) << "\t name " << it->GetName() << endl; + } + fout << endl; + } +} + + +//------------------------------------------------------------------------------ +// It writes the events list to be proceed in the next date +//------------------------------------------------------------------------------ +void Schedule::WriteNextEvents(ofstream &fout) +{ + if (!nextevents->empty()){ + for (list<Event>::iterator it=nextevents->begin(); it!=nextevents->end(); ++it) { + fout << "Event date " << it->GetDate() << "\t in node " << (it->GetNode())->GetName() << "\t type " << it->GetDescription() << endl; + } + } + + if (!nextcontrolledevents->empty()){ + for (list<ControlledEvent>::iterator it=nextcontrolledevents->begin(); it!=nextcontrolledevents->end(); ++it) { + fout << "Event date " << it->GetDate() << "\t in node " << (it->GetNodeId()) << "\t type " << it->GetDescription() << endl; + } + } + + if (!nextbreakpoints->empty()){ + for (list<Breakpoint>::iterator it=nextbreakpoints->begin(); it!=nextbreakpoints->end(); ++it) { + fout << "Breakpoint date " << it->GetDate(simulation->stime->GetCurrentDate()) << "\t in node " << (it->GetNodeId()) << "\t type " << it->GetDescription() << endl; + } + } +} + +//------------------------------------------------------------------------------ +// Compute events +//------------------------------------------------------------------------------ +void Schedule::ComputeEvents(BPN *_bpn) +{ + _bpn->ComputeNextEventDTF(dtf); + _bpn->ComputeNextEventCPE(cpe); + _bpn->ComputeNextEventDTE(dte); + _bpn->ComputeNextEventBOB(bob); + _bpn->ComputeNextEventDOB(dob); + _bpn->ComputeNextEventBBD(bbd); + _bpn->ComputeNextEventTBM(tbm); + _bpn->ComputeNextEventBMOB(bmob); + _bpn->ComputeNextEventOBD(obd); + _bpn->ComputeNextEventBD(bd); + _bpn->ComputeNextEventBBF(bbf); + _bpn->ComputeNextEventPSQ(psq); + _bpn->ComputeNextEventRBF(rbf); +} + +//------------------------------------------------------------------------------ +// Compute next date +//------------------------------------------------------------------------------ +void Schedule::ComputeNextDate(BPN *_bpn, double duration) +{ + // clean all non-controlled events + dtf->clear(); + cpe->clear(); + dte->clear(); + bob->clear(); + dob->clear(); + bbd->clear(); + tbm->clear(); + bmob->clear(); + obd->clear(); + bd->clear(); + bbf->clear(); + psq->clear(); + rbf->clear(); + + ComputeEvents(_bpn); +} + +//------------------------------------------------------------------------------ +// Compute next event +//------------------------------------------------------------------------------ +double Schedule::ComputeNextEvent(double duration) +{ + double nextdate = duration; + + if (!dtf->empty()) + nextdate = ComputeNextEventDate(dtf, nextdate, Discr_trans_fires); + + if (!cpe->empty()) + nextdate = ComputeNextEventDate(cpe, nextdate, Cont_place_empty); + + if (!dte->empty()) + nextdate = ComputeNextEventDate(dte, nextdate, Discr_trans_enabled); + + if (!bob->empty()) + nextdate = ComputeNextEventDate(bob, nextdate, Becomes_output_batch); + + if (!dob->empty()) + nextdate = ComputeNextEventDate(dob, nextdate, Destr_output_batch); + + if (!bbd->empty()) + nextdate = ComputeNextEventDate(bbd, nextdate, Batch_becomes_dense); + + if (!tbm->empty()) + nextdate = ComputeNextEventDate(tbm, nextdate, Two_batches_meet); + + if (!bmob->empty()) + nextdate = ComputeNextEventDate(bmob, nextdate, Batch_meets_output_batch); + + if (!obd->empty()) + nextdate = ComputeNextEventDate(obd, nextdate, Output_batch_decongestion); + + if (!bd->empty()) + nextdate = ComputeNextEventDate(bd, nextdate, Batch_decongestion); + + if (!bbf->empty()) + nextdate = ComputeNextEventDate(bbf, nextdate, Batch_becomes_free); + + if (!psq->empty()) + nextdate = ComputeNextEventDate(psq, nextdate, Place_steady_quan); + + if (!rbf->empty()) + nextdate = ComputeNextEventDate(rbf, nextdate, Remaining_becomes_freesteadyquan); + + + // controlled events + if (!tfce->empty()) + nextdate = ComputeNextControlledEventDate(tfce, nextdate, Trans_flow_ce); + + if (!psce->empty()) + nextdate = ComputeNextControlledEventDate(psce, nextdate, Place_speed_ce); + + // breakpoint + if (!breakpoint->empty()) + nextdate = ComputeNextBreakpointDate(breakpoint, nextdate); + + return (nextdate); +} + +//------------------------------------------------------------------------------ +// Compute a date for an event list +//------------------------------------------------------------------------------ +double Schedule::ComputeNextEventDate(list<Event> *evl, double nextdate, ev_type type) +{ + while (!evl->empty()){ + Event *e = new Event; + *e = evl->front(); + evl->pop_front(); + double eventdate = e->GetDate(); + + if (abs(eventdate - nextdate) < PRF::prf.Min_Err()) { // both events in the same date + nextevents->push_back(*e); + } + + if (((nextdate - eventdate) > PRF::prf.Min_Err()) && (eventdate >= simulation->stime->GetCurrentDate())) { + nextdate = eventdate; + nextevents->clear(); + nextevents->push_back(*e); + } + else{ + delete e; + } + } + + for (list<Event>::iterator it=nextevents->begin(); it!=nextevents->end(); ++it) { + double eventdate = it->GetDate(); + if (nextdate < eventdate) + nextdate = eventdate; + } + return (nextdate); +} + +//------------------------------------------------------------------------------ +// Compute a date for a controlled event list +//------------------------------------------------------------------------------ +double Schedule::ComputeNextControlledEventDate(list<ControlledEvent> *cevl, double nextdate, ev_type type) +{ + int numerofcontrolledevents = cevl->size(); + + for (int i=0; i<numerofcontrolledevents; i++){ + ControlledEvent *ce = new ControlledEvent; + *ce = cevl->front(); + cevl->pop_front(); + double eventdate = ce->GetDate(); + + if (eventdate <= simulation->stime->GetCurrentDate()){ + continue; + } + else{ + cevl->push_back(*ce); + } + + if (eventdate == nextdate) { // both events in the same date + nextcontrolledevents->push_back(*ce); + } + + if (eventdate < nextdate ) { + nextdate = eventdate; + nextevents->clear(); + nextcontrolledevents->clear(); + nextcontrolledevents->push_back(*ce); + } + } + + return (nextdate); +} + +//------------------------------------------------------------------------------ +// Compute a date for the next breakpoint +//------------------------------------------------------------------------------ +double Schedule::ComputeNextBreakpointDate(list<Breakpoint> *bpl, double nextdate) +{ + int numberofbreakpoints = bpl->size(); + nextbreakpoints->clear(); + + if (nextevents->empty() && nextcontrolledevents->empty()){ + return(nextdate); + } + + for (int i=0; i<numberofbreakpoints; i++){ + Breakpoint *bp = new Breakpoint; + *bp = bpl->front(); + bpl->pop_front(); + double breakpointdate = bp->GetDate(simulation->stime->GetCurrentDate()); + + if (breakpointdate <= simulation->stime->GetCurrentDate()){ + continue; + } + else{ + bpl->push_back(*bp); + } + + if (breakpointdate == nextdate) { // both events in the same date + nextbreakpoints->push_back(*bp); + } + + if (breakpointdate < nextdate) { + nextdate = breakpointdate; + nextevents->clear(); + nextcontrolledevents->clear(); + nextbreakpoints->clear(); + nextbreakpoints->push_back(*bp); + } + } + return (nextdate); +} + +//------------------------------------------------------------------------------ +// Process events +// TODO - process controled events +//------------------------------------------------------------------------------ +void Schedule::ProcessEvents(BPN *_bpn) +{ + int type; + double speed; + + while (!nextcontrolledevents->empty()){ + ControlledEvent *ce = new ControlledEvent; + *ce = nextcontrolledevents->front(); + nextcontrolledevents->pop_front(); + + type = ce->GetType(); + + switch(type){ + case Place_speed_ce : { + TriangularBatchPlace *tbp = ce->GetNode(_bpn); + tbp->SetAndRecomputeSpeed(ce->GetValue()); + } + break; + case Trans_flow_ce : { + BatchTransition *bt = ce->GetNode(_bpn); + Flow *fl = bt->GetFlow(); + fl->SetMaximumFlow(ce->GetValue()); + bt->Print(cout); + } + break; + } + + } + + while (!nextevents->empty()){ + Event *e = new Event; + *e = nextevents->front(); + nextevents->pop_front(); + + switch(e->GetType()){ + case Discr_trans_fires : DiscreteTransition *dt = e->GetNode(); + dt->FireDiscreteTransition(); + + break; + } + } + +} + +//------------------------------------------------------------------------------ +// Process breakpoints - this function print the bpn at the breakpoint +//------------------------------------------------------------------------------ +void Schedule::ProcessBreakpoints(BPN *_bpn) +{ + while (!nextbreakpoints->empty()){ + Breakpoint *bp = new Breakpoint; + *bp = nextbreakpoints->front(); + nextbreakpoints->pop_front(); + + bp->PrintPlaceTransition(_bpn, std::cout); + } +} diff --git a/src/simul/schedule.h b/src/simul/schedule.h new file mode 100644 index 0000000..aa7e707 --- /dev/null +++ b/src/simul/schedule.h @@ -0,0 +1,85 @@ +//====================================================================================// +// // +// Schedule class // +// // +//====================================================================================// +// This File: schedule.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 08/may/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 24/jan/20 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef SCHEDULE_H +#define SCHEDULE_H + +extern Simulate *simulation; + +class Schedule +{ + public: + Schedule(); + virtual ~Schedule(); + + void Copy(const Schedule *_schedule); + + //input functions + void AddEvent(Event& e, ev_type type); + void AddControlledEvent(ControlledEvent& ce, ev_type type); + void AddBreakpoint(Breakpoint& bp); + + //output functions + char* GetEventDescription(ev_type type); + char* GetBreakpointDescription(breakpoint_type type); + int IsEmpty(); + void Clean(list<ControlledEvent> *cevl, double _currentdate); + void CleanAll(); + + //print functions + void PrintEvents(ostream &fout); + void PrintCE(ostream &fout); + void PrintBP(ostream &fout); + void Print(ostream &fout); + void WriteEvents(ofstream & fout); + void WriteCE(ofstream & fout); + void WriteBP(ofstream & fout); + void WriteNextEvents(ofstream & fout); + + //simulation functions + void ComputeEvents(BPN *_bpn); + void ComputeNextDate(BPN *_bpn, double duration); + double ComputeNextEvent(double duration); + double ComputeNextEventDate(list<Event> *evl, double nextdate, ev_type type); + double ComputeNextControlledEventDate(list<ControlledEvent> *cevl, double nextdate, ev_type type); + double ComputeNextBreakpointDate(list<Breakpoint> *bpl, double nextdate); + void ProcessEvents(BPN *_bpn); + void ProcessBreakpoints(BPN *_bpn); + + protected: + list<Event> *dtf; // Discrete Transition is Fired + list<Event> *cpe; // Continuous Place becomes Empty + list<Event> *dte; // Discrete Transition becomes Enable + list<Event> *bob; // Batch becomes an Output Batch + list<Event> *dob; // Destruction of an Output Batch + list<Event> *bbd; // Batch Becomes Dense + list<Event> *tbm; // Two Batches Meet + list<Event> *bmob; // A batch meets an output batch + list<Event> *obd; // Decongestion of the output batch + list<Event> *bd; // Decongestion of a batch in contact head + list<Event> *bbf; // Full decongestion of an alone batch + list<Event> *psq; // Place reaches Steady marking quantity + list<Event> *rbf; // Remaining quantity passed by an input transition becomes equal to free steady quantity. + + list<ControlledEvent> *tfce; // Transition maximum Flow changes + list<ControlledEvent> *psce; // Place maximum Speed changes + + list<Breakpoint> *breakpoint; // breakpoint to print results + + list<Event> *nextevents; // list of the next events to be simulated + list<ControlledEvent> *nextcontrolledevents; // list of the next controlled events to be simulated + list<Breakpoint> *nextbreakpoints; // list of the next breakpoint to be simulated + + + private: +}; + +#endif // SCHEDULE_H diff --git a/src/simul/simtime.cpp b/src/simul/simtime.cpp new file mode 100644 index 0000000..8fda6c2 --- /dev/null +++ b/src/simul/simtime.cpp @@ -0,0 +1,99 @@ +//====================================================================================// +// // +// Simtime class // +// // +//====================================================================================// +// This File: simtime.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 11/may/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 11/may/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ +Simtime::Simtime() +{ + currentdate = 0.0; + previousdate = 0.0; + nextdate = 0.0; +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Simtime::~Simtime() +{ + //dtor +} + +//------------------------------------------------------------------------------ +// Set all dates to zero +//------------------------------------------------------------------------------ +void Simtime::Reset() +{ + previousdate = currentdate = nextdate = 0.0; +} + +//------------------------------------------------------------------------------ +// Permute dates +//------------------------------------------------------------------------------ +void Simtime::Permute() +{ + previousdate = currentdate; + currentdate = nextdate; +} + +//------------------------------------------------------------------------------ +// Compute steptime +//------------------------------------------------------------------------------ +double Simtime::StepTime() +{ + return (currentdate - previousdate); +} + +//------------------------------------------------------------------------------ +// Set the next date +//------------------------------------------------------------------------------ +void Simtime::SetNextDate(double _nd) +{ + nextdate = _nd; +} + + +//------------------------------------------------------------------------------ +// Return the previous date +//------------------------------------------------------------------------------ +double Simtime::GetPreviousDate() +{ + return previousdate; +} + +//------------------------------------------------------------------------------ +// Return the current date +//------------------------------------------------------------------------------ +double Simtime::GetCurrentDate() +{ + return currentdate; +} + +//------------------------------------------------------------------------------ +// Return the next date +//------------------------------------------------------------------------------ +double Simtime::GetNextDate() +{ + return nextdate; +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Simtime::Print(ofstream &fout) +{ + cout << "Previous date = " << previousdate; + cout << "Current date = " << currentdate; + cout << "Next date = " << nextdate; +} diff --git a/src/simul/simtime.h b/src/simul/simtime.h new file mode 100644 index 0000000..b5fd072 --- /dev/null +++ b/src/simul/simtime.h @@ -0,0 +1,41 @@ +//====================================================================================// +// // +// Simtime class // +// // +//====================================================================================// +// This File: simtime.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 11/may/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 11/may/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef SIMTIME_H +#define SIMTIME_H + +class Simtime +{ + public: + Simtime(); + virtual ~Simtime(); + + void Reset(); // set all dates to zero + void Permute(); // permute previousdate to currentdate and currentdate to nextdate + double StepTime(); // Compute the difference between currentdate and nextdate + + void SetNextDate(double _nd); + double GetPreviousDate(); + double GetCurrentDate(); + double GetNextDate(); + + //print + void Print(ofstream &fout); + + protected: + double currentdate; + double previousdate; + double nextdate; + + private: +}; + +#endif // SIMTIME_H diff --git a/src/simul/simulate.cpp b/src/simul/simulate.cpp new file mode 100644 index 0000000..24a8a29 --- /dev/null +++ b/src/simul/simulate.cpp @@ -0,0 +1,352 @@ +//====================================================================================// +// // +// Simulate class // +// // +//====================================================================================// +// This File: simulate.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 11/may/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 11/may/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + +//------------------------------------------------------------------------------ +// Empty contructor +//------------------------------------------------------------------------------ +Simulate::Simulate() +{ + simulationtime = 0.0; + simulationsteps = 0; + + sbpn = NULL; + sschedule = NULL; + stime = NULL; +} + +//------------------------------------------------------------------------------ +// Its simulate the bpn model with controlled events in schedule for maxtime +//------------------------------------------------------------------------------ +Simulate::Simulate(BPN *_bpn, Schedule *_schedule) +{ + simulationtime = 0.0; + simulationsteps = 0; + + sbpn = new BPN; + sbpn->Copy(_bpn); + + sschedule = new Schedule; + sschedule->Copy(_schedule); + + stime = new Simtime; + stime->Reset(); +} + +//------------------------------------------------------------------------------ +// Destructor +//------------------------------------------------------------------------------ +Simulate::~Simulate() +{ + if (sbpn) + delete sbpn; + if (sschedule) + delete sschedule; + if (stime) + delete stime; +} + + +//------------------------------------------------------------------------------ +// It assigns a file name +//----------------------------------------------------------------------------- +void Simulate::Baptise(simuleau_name file) +{ + strcpy(filename, file); +} + + +//------------------------------------------------------------------------------ +// return the sbpn pointer +//----------------------------------------------------------------------------- +BPN * Simulate::GetBpn() +{ + return sbpn; +} + +//------------------------------------------------------------------------------ +// return the sschedule pointer +//----------------------------------------------------------------------------- +Schedule * Simulate::GetSchedule() +{ + return sschedule; +} + +//------------------------------------------------------------------------------ +// Return true if there are a bpn model in memory +//------------------------------------------------------------------------------ +int Simulate::IsEmpty() +{ + if (sbpn != NULL && sschedule != NULL) + return false; + else + return true; +} + +//------------------------------------------------------------------------------ +// Start the model simulation +//------------------------------------------------------------------------------ +int Simulate::Start(double maxtime, simuleau_options option) +{ + simuleau_name dyn_level_name; + ofstream fout; + Timer T; + + int result = 0; + int conflict = 0; + double precision = PRF::prf.Min_Err(); + double steptime = maxtime; + + strcpy(dyn_level_name, "dyn/"); strcat(dyn_level_name, filename); + Open_File(dyn_level_name, dyn_file, fout); + + //verify conflit + sbpn->ResearchStructuralConflict(); + + if (option == simulate_xct){ // no external events + sschedule->CleanAll(); + } + + // start simulation + simulationtime = maxtime; + simulationsteps = 0; + + WriteInfo(fout); + + stime->Reset(); + T.clear(); + T.start(); + + //sbpn->ComputeSteadyState(); + switch(option){ + case simulate_onoff : + case simulate_mf_onoff : sbpn->ComputeSteadyFiringQuantity(); + break; + } + + + + do{ + stime->Permute(); + WriteDate(fout); + + cout << "================================================\n" ; + cout << "Current date: " << stime->GetCurrentDate() << endl; + cout << "================================================\n" ; + + steptime = stime->StepTime(); // compute the difference betwen current and previous date + switch(option){ + case simulate_onoff : + case simulate_mf_onoff : sbpn->ComputeCurrentFiringQuantity(steptime); // compute current firing quantity from initial marking //currentFiringquantity is not in sbpn. + break; + } + + +/* fout << "================================================\n" ; + fout << "At the end of the step\n" ; + fout << "================================================\n" ; + WriteBPNMarks(fout); +*/ + sbpn->ComputeNewMarks(steptime); + + sschedule->ProcessEvents(sbpn); + + sbpn->DestructBatches(); + + sbpn->MergeBatches(); + + sbpn->DestructBatches(); + + + + fout << "================================================\n" ; + fout << "At the begin of the step\n" ; + fout << "================================================\n" ; + + + WriteBPNMarks(fout); +// sbpn->Print(ofstream &fout); + + sbpn->ComputeTransitionsStates(); + + switch(option){ + case simulate : + case simulate_xct : sbpn->ComputeIFF(); + break; + case simulate_onoff : sbpn->ComputeCFF(); // on/off control method + break; + case simulate_mf_onoff : sbpn->ComputeMCFF(); // on/off control method + break; + } + + + WriteBPNFlows(fout); + if (sbpn->IsSteadyStateReached() && (sbpn->NumberOfDiscretePlaces()==0)){ + result = 5; + cout << " Steady state reached\n" + << " stopping simulation at " << stime->GetCurrentDate() << endl; + break; + } + + sschedule->ProcessBreakpoints(sbpn); + + // Create Batches + sbpn->CreateBatches(); + + sbpn->ComputeBatchesBehaviours(); + + conflict = sbpn->VerifyConflict(); + if (conflict){ + result = conflict + 2; + cout << " conflict found\n" + << " stopping simulation at " << stime->GetCurrentDate() << endl; + break; + } + + + sbpn->ReserveMarks(); + + sschedule->ComputeNextDate(sbpn, simulationtime); + WriteEvents(fout); + + stime->SetNextDate(sschedule->ComputeNextEvent(simulationtime)); + WriteNextEvents(fout); + + simulationsteps++; + if (sschedule->IsEmpty()){ + result = 2; + } + if (stime->GetNextDate() > simulationtime){ + result = 1; + } + + + sbpn->SetBehaviourFunctions(); + cout << endl << endl; + + + } while ((result == 0) && ( conflict == 0)); + T.stop(); + + WriteEnd(fout, result); + Close_File(dyn_level_name, dyn_file, fout); + + cout << "\nFinal simulation time: " << stime->GetCurrentDate() << endl; + cout << "Number of simulation steps: " << simulationsteps; + Notify_Time_Spend(T, "simulation of a BPN model"); + +} + +//------------------------------------------------------------------------------ +// Print +//------------------------------------------------------------------------------ +void Simulate::Print(ostream &fout) +{ + if (stime != NULL){ + fout << "Simulated time: " << stime->GetCurrentDate() << endl; + fout << "Simulated step: " << simulationsteps << endl << endl; + } + + sbpn->Print(fout); + sschedule->Print(fout); +} + +//------------------------------------------------------------------------------ +// It writes model and simulation informations +//------------------------------------------------------------------------------ +void Simulate::WriteInfo(ofstream &fout) +{ + fout << "Model name: " << sbpn->GetName() << endl; + fout << "Simulation time: " << simulationtime << endl; + fout << "Precision: " << PRF::prf.Min_Err() << endl << endl; + + fout << "Number of places: " << sbpn->NumberOfPlaces() << endl; // specify discr, ..... + fout << "Number of transitions: " << sbpn->NumberOfTransitions() << endl; +} + +//------------------------------------------------------------------------------ +// It writes current date +//------------------------------------------------------------------------------ +void Simulate::WriteDate(ofstream &fout) +{ + fout << "==================================================="<< endl; + fout << "Current date : " << stime->GetCurrentDate() << endl; + fout << "==================================================="<< endl << endl; +} + +//------------------------------------------------------------------------------ +// It writes current BPN marks +//------------------------------------------------------------------------------ +void Simulate::WriteBPNMarks(ofstream &fout) +{ + sbpn->WritePlaces(fout); +} + + +//------------------------------------------------------------------------------ +// It writes continuous and batch transition flows +//------------------------------------------------------------------------------ +void Simulate::WriteBPNFlows(ofstream &fout) +{ + sbpn->WriteFlows(fout); +} + +//------------------------------------------------------------------------------ +// It writes the events list +//------------------------------------------------------------------------------ +void Simulate::WriteEvents(ofstream &fout) +{ + fout << endl << "Events" << endl; + sschedule->WriteEvents(fout); + fout << endl; + + sschedule->WriteCE(fout); + + sschedule->WriteBP(fout); + + + +} + +//------------------------------------------------------------------------------ +// It writes the next events to be proceed +//------------------------------------------------------------------------------ +void Simulate::WriteNextEvents(ofstream &fout) +{ + fout << "Next events to proceed" << endl; + + sschedule->WriteNextEvents(fout); + fout << endl; +} + +//------------------------------------------------------------------------------ +// It writes simulation steps, time, .. +//------------------------------------------------------------------------------ +void Simulate::WriteEnd(ofstream &fout, int code) +{ + fout << endl; + fout << "Final simulation time: " << stime->GetCurrentDate() << endl; + fout << "Number of simulation steps: " << simulationsteps << endl; + + switch (code){ + case 1 : fout << "Maximal simulation time reached" << endl; + break; + case 2 : fout << "No more events in the schedule" << endl; + break; + case 3 : fout << "Conflit in discrete place - Simulation was stopped" << endl; + break; + case 4 : fout << "Conflit in continuous place - Simulation was stopped" << endl; + break; + case 5 : fout << "Steady state was reached" << endl; + break; + } +} diff --git a/src/simul/simulate.h b/src/simul/simulate.h new file mode 100644 index 0000000..fd6fd64 --- /dev/null +++ b/src/simul/simulate.h @@ -0,0 +1,65 @@ +//====================================================================================// +// // +// Simulate class // +// // +//====================================================================================// +// This File: simulate.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 11/may/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 11/may/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef SIMULATE_H +#define SIMULATE_H +#include "interf.h" + +class Simulate +{ + public: + Simulate(); + Simulate(BPN *_bpn, Schedule *_schedule); + virtual ~Simulate(); + + void Baptise(simuleau_name file); + + BPN * GetBpn(); + Schedule * GetSchedule(); + + int IsEmpty(); + + int Start(double maxtime, simuleau_options option); + + void Print(ostream &fout); + void PrintBPN(); + void PrintSchecule(); + + + //friend class Schedule; + //friend class BPN; + //friend class ::Node; + +// friend double Schedule::ComputeNextEventDate(list<Event> *evl, double nextdate, ev_type type); + + BPN *sbpn; + Schedule *sschedule; + Simtime *stime; + + protected: + double simulationtime; + int simulationsteps; + + simuleau_name filename; //output file name + + void WriteInfo(ofstream &fout); // write model and simulation informations + void WriteDate(ofstream &fout); // write current date + void WriteBPNMarks(ofstream &fout); // write current BPN marks + void WriteBPNFlows(ofstream &fout); // write continuous and batch transition flows + void WriteEvents(ofstream &fout); // write the events list + void WriteNextEvents(ofstream &fout); // write the next events to be proceed + void WriteEnd(ofstream &fout, int code); // write simulation step, time, ... + + + private: +}; + +#endif // SIMULATE_H diff --git a/src/simuleau.cpp b/src/simuleau.cpp new file mode 100644 index 0000000..f587bc3 --- /dev/null +++ b/src/simuleau.cpp @@ -0,0 +1,180 @@ +//====================================================================================// +// // +// SIMULEAU Main // +// // +//====================================================================================// +// This File: simuleau.cpp Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 12/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 12/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#include "simuleau.h" + + +//====================================================================================// +// Global Variables // +//====================================================================================// + BPN *bpn = NULL; + Schedule *schedule = NULL; + Simulate *simulation = NULL; + PRF prf; + + + +//====================================================================================// +// BPN compilation function prototype - glc.y // +//====================================================================================// +void Compile_Network(const simuleau_name simuleau_level_name, const simuleau_name str_level_name); + +//====================================================================================// +void Compile_BPN() // Main compile peration // +//====================================================================================// +{ // BPN model name in all directories handled by SIMULEAU + simuleau_name model_name; // current directory (just the name, no paths, no extensions) + simuleau_name bpn_level_name; // directory where the textual network is (./*.bpn) + simuleau_name str_level_name; // directory to store the internal structure(./str/*.str) + + Timer T; // timer to inform total time spent + + cout << "\nCompilation of a BPN model"; + T.clear(); + Ask_an_Existing_File_Name(bpn_level_name, bpn_file); + Get_Only_the_File_Name(bpn_level_name, model_name); + strcpy(str_level_name, "str/"); strcat(str_level_name, model_name); + if (Permission_to_Proceed(str_level_name, str_file)) { // .bpn compilation + T.start(); + cout << "Compile_Network\n"; + Compile_Network(bpn_level_name, str_level_name); +// simulation = new Simulate(bpn, schedule); // prepare to simulation + T.stop(); + Notify_Time_Spend(T, "compilation of a BPN model"); + } +} + +//====================================================================================// +bool Start_Up_BPN() // Main simulation operation // +//====================================================================================// +{ + bool answer = false; + simuleau_name name; + simuleau_name bpn_level_name; // directory where the textual network is (./*.bpn) + simuleau_name dyn_level_name; // directory to store the simulation results(./dyn/*.dyn) + + if (bpn == NULL){ + cout << "There is no Batch Petri Net model (bpn) in memory.\n"; + cout << "You must compile a bpn using the option 1 in main menu.\n"; + return(false); + } + + simulation = new Simulate(bpn, schedule); // prepare to simulation + cout << "\nSimulation of the model '" << bpn->GetName() << "' (" + << bpn->NumberOfPlaces() << " places - " << bpn->NumberOfTransitions() << " transitions)\n"; + Ask_a_File_Name(bpn_level_name, dyn_file); + Get_Only_the_File_Name(bpn_level_name, name); + strcpy(dyn_level_name, "dyn/"); strcat(dyn_level_name, name); + + if (Permission_to_Proceed(dyn_level_name, dyn_file)) { + simulation->Baptise(name); + PRF::prf.Max_Time(Ask_a_Simulation_Time()); + answer = true; + } + + return(answer); +} + +//====================================================================================// +bool Start_Up_BPN_SteadyState() // Compute Steady state operation // +//====================================================================================// +{ + bool answer = false; + simuleau_name name; + simuleau_name bpn_level_name; // directory where the textual network is (./*.bpn) + simuleau_name dyn_level_name; // directory to store the simulation results(./dyn/*.dyn) + + if (bpn == NULL){ + cout << "There is no Batch Petri Net model (bpn) in memory.\n"; + cout << "You must compile a bpn using the option 1 in main menu.\n"; + return(false); + } + + cout << "\nComputation of the steady state for the model '" << bpn->GetName() << "' (" + << bpn->NumberOfPlaces() << " places - " << bpn->NumberOfTransitions() << " transitions)\n"; + + if (Ask_an_Answer("This procedure will modify the steady state. Procede anyway (y/n)?")) { + answer = true; + } + + return(answer); +} + +//====================================================================================// +// SIMULEAU Main // +//====================================================================================// +int main() +{ + bool cont = true; + simuleau_name name; + + //cout.setf(ios::fixed); + //cout.precision(16); + //set_new_handler(Communicate_Out_of_Memory); + Create_Temporary_Directories(); + do { + switch (Welcome_Get_Simuleau_Option()) { +//====================================================================================// +// Compiling Operations // +//====================================================================================// + case compile : Compile_BPN(); break; +//====================================================================================// +// Simulation Operations // +//====================================================================================// + case simulate_xct : if(Start_Up_BPN()){ + simulation->Start(PRF::prf.Max_Time(), simulate_xct); + } + break; + case simulate : if(Start_Up_BPN()){ + simulation->Start(PRF::prf.Max_Time(), simulate); + } + break; + case simulate_onoff : if(Start_Up_BPN()){ + simulation->Start(PRF::prf.Max_Time(), simulate_onoff); + } + break; + case compute_steadystate : if(Start_Up_BPN_SteadyState()){ + bpn->ComputeSteadyState(); + } + + break; + case compute_periodicsteadystate : if(Start_Up_BPN_SteadyState()){ + bpn->ComputePeriodicSteadyState(); + } + + break; + case simulate_mf_onoff : if(Start_Up_BPN()){ + simulation->Start(PRF::prf.Max_Time(), simulate_mf_onoff); + } + break; + +//====================================================================================// +// Inspect Operations // +//====================================================================================// + case see_bpn : See_BPN(); break; + case see_place : See_place(); break; + case see_trans : See_trans(); break; + case see_events : See_events(); break; + + + +//====================================================================================// +// Other Operations // +//====================================================================================// + case credits : Show_Credits(); break; + case goodbye : cont = false; break; + default : Programming_Error("invalid SIMULEAU option", 0000) + } + } while (cont); + Say_Goodbye(); + return(EXIT_SUCCESS); +} + diff --git a/src/simuleau.h b/src/simuleau.h new file mode 100644 index 0000000..193630b --- /dev/null +++ b/src/simuleau.h @@ -0,0 +1,259 @@ +//====================================================================================// +// // +// SIMULEAU Global Declarations // +// // +//====================================================================================// +// This File: simuleau.h Language: C++ (xlC and CC) // +// Software: SIMULEAU // +//====================================================================================// +// Creation: 12/apr/16 by: Leonardo.Brenner@lsis.org // +// Last Change: 28/apr/16 by: Leonardo.Brenner@lsis.org // +//====================================================================================// +#ifndef SIMULEAU_H +#define SIMULEAU_H + +#include <fstream> // file streams (i/o) +#include <iostream> // std i/o with streams (cin, cout, cerr) +#include <iomanip> // i/o manipulators (setiosflags-scientific) +#include <string.h> // string manipulation (strcpy, strcat) +#include <math.h> // absolute values (abs), square roots (sqrt) +#include <cmath> // std::abs +#include <limits.h> // maximum and minimum values to int, float, etc +#include <new> // handler for new commands (test for allocation) +#include <stdio.h> // i/o standard of C language (used for the parser) +#include <stdlib.h> // standard library of C language +#include <unistd.h> // +#include <sys/stat.h> // system file manipulation functions +#include <sys/types.h> // +#include <list> // list manipulation +#include <stack> // stack manipulation +#include <glpk.h> // linear program solver + + + +using namespace std; + +//====================================================================================// +// Release Date ******************** CHANGE THIS DATE FOR NEW RELEASES OF SIMULEAU // +//====================================================================================// + +#define __RELEASE_DATE__ "Apr 30 2016" + + +//====================================================================================// +// BPN classes // +//====================================================================================// +class BPN; // Main BPN class (main structure) 1100 +class Node; // Node class (node main structure) 1200 +class Place; // Place class (place main structure) 1300 +class DiscretePlace; // DiscretePlace class (discrete place structure) 1300 +class ContinuousPlace; // ContinuousPlace class (continuous place structure)1300 +class BatchPlace; // BatchPlace class (batch place structure) 1300 +class TriangularBatchPlace; // TriangularBatchPlace class + // (traingular batch place structure) 1300 + +class Transition; // Transition class (transition main structure) 1400 +class DiscreteTransition; // DiscreteTransition class + // (discrete transition structure) 1400 +class ContinuousTransition; // ContinuousTransition class + // (continuous transition structure) 1400 +class BatchTransition; // BatchTransition clas (batch transition structure) 1400 +class Arc; // Arc class (arc main structure) 1500 +class Batch; // Batch class (batch main structure) 1600 +class ControllableBatch; // ControllableBatch class + // (controllable batch structure) 1600 +class Flow; // Flow class (flow main structure) 1700 + +class Event; // Event class (event main structure) 1800 +class ControlledEvent; // ControlledEvent class(Controlled event structure) 1800 +class Breakpoint; // Breakpoint class (Breakpoint structure) 1850 +class Schedule; // Schedule class (Schedule main structure) 1900 +class Simtime; // Simtime class (simtime structure) 2000 +class Simulate; // Simulate class (simulate structure) 2100 + + + +//====================================================================================// +// User Interface // +//====================================================================================// +class PRF; // User Preferences (main structure) 6100 + +//====================================================================================// +// Miscelaneous // +//====================================================================================// +class Timer; // general chronometers from pac++ + +//====================================================================================// +// Types of Files Handled by Simuleau // +//====================================================================================// + +enum file_types // all files handled by Simuleau + { bpn_file , // textual description of BPN + str_file , // internal representation of BPN STRucture + xct_file , // textual description of eXTernal Controlled events + dyn_file , // messages of DYNamics of BPN + tim_file , // messages of TIMes spend in Simuleau software + dbg_file , // textual output (Readable) with DeBuGging information + prf_file , // user PReFerences for parameters (numerical precision, etc) + dot_file , // names without extension + err_file }; // unrecognized extension + +//====================================================================================// +// Basic Definitions // +//====================================================================================// +const int no = 0; // used in formalisation variable +const int yes = 1; // used in formalisation variable +const double zero = 0.0; // double sized constants to avoid +const double one = 1.0; // problems passing parameters +const double two = 2.0; +const double epsilon = 1e-5; // a small double valeu +const double close_to_zero = 1e-16; // a very small double valeu +const double round_zero = 1e-12; // a rather small double valeu +const double visual_zero = 1e-5; // smallest value displayed as decimal +const int simuleau_precision = 10; // precision to handle (i/o) double values +const int max_integer = INT_MAX; // maximum integer (signed) +const int min_integer = INT_MIN; // minimum integer (signed) +const double max_float = 1e+50; // max. float (actually just a huge one) +const double min_float = -1e+50; // min. float (actually just a tiny one) +#ifdef _CC_COMPILER_ + typedef int bool; // boolean variables + const bool true = 1; // gcc and other non-standart c++ + const bool false = 0; // compilers have built-in bool types +#endif +const int mem_unit = 1024; // unit of memory space (Kbytes) + +//====================================================================================// +// Simuleau Name Definitions // +//====================================================================================// + +const int max_simuleau_name = 128; // Maximum size (actually the last 4 are ".ext") + +typedef char simuleau_name[max_simuleau_name]; + // User Definided Names for any Simuleau Entity + +//====================================================================================// +// Identifiers Definitions // +//====================================================================================// +typedef int any_id; // for identifiers of any kind +const any_id no_id = -1; + +typedef int node_id; // for node (anykind) +const node_id no_node = -1; +const node_id fst_node = 0; + +typedef int place_id; // for place (anykind) +const place_id no_place = -1; +const place_id fst_place = 0; + +typedef int trans_id; // for transtion (anykind) +const trans_id no_trans = -1; +const trans_id fst_trans = 0; + +typedef int batch_id; // for batch in a place +const batch_id no_batch = -1; +const batch_id fst_batch = 0; + +typedef int ev_id; // for events +const ev_id no_ev = -1; +const ev_id fst_ev = 0; + +typedef int m_coord; // for pre/post matrices coordinates +const m_coord no_coord = -1; +const m_coord fst_m_coord = 0; // the first coordinate (in matrices) + +typedef double pl_cont_fed; +const pl_cont_fed Not_fed = 0.0; +const pl_cont_fed Fed = 0.5; // The place has an input flow + + +//====================================================================================// +// Pre-defined Enumerations // +//====================================================================================// +enum node_type { Place_nd , Transition_nd }; // Place or Transition node +enum place_type { Discrete_pl , Continuous_pl , Batch_pl, Triangular_pl }; + // Discrete, Continuous, Batch and Triangular Batch places +enum trans_type { Discrete_tr , Continuous_tr , Batch_tr }; + // Discrete, Continuous and Batch transitions +enum batch_type { Batch_bt , Controllable_bt }; // Batches types +enum node_state { No_state }; // No state, ... +enum Batch_place_behaviour { Accumulating_behaviour=2 }; // No behaviour, ... +enum ctrl_batch_state{ No_st , Free_st , Congested_st }; + // States of a Controllable batch +enum ctrl_batch_behaviour { No_behaviour , + Free_behaviour , + Congesting_behaviour , + Uncongesting_behaviour }; + // Behaviours of a controllable batch + +enum ev_class { Internal_ev, External_ev, Controlled_ev }; + // Internal, External and Controlled event classification +enum ev_type { No_event, // No event + Discr_trans_fires, // Discrete transition is fired + Cont_place_empty, // Continuous place becomes empty + Discr_trans_enabled, // Discrete transition becomes enable + Becomes_output_batch,// A batch becomes an output batch + Destr_output_batch, // Destruction of an output batch + Batch_becomes_dense, // Full accumulation/congestion of a batch + Two_batches_meet, // Two batches meet + Batch_meets_output_batch, // A batch meet an output batch + Output_batch_decongestion, // Decongestion of the output batch + Batch_decongestion, // Decongestion of a batch in contact head + Batch_becomes_free, // Full decongestion of an alone batch + Place_steady_quan, // Place reaches Steady marking Quantity + Remaining_becomes_freesteadyquan, //Remaining quantity becomes free steady quantity + + + Trans_flow_ce, // A controled event changes the maximum + // flow of a transition + Place_speed_ce // A controlled event changes the maximum + // speed of a batch place + }; +enum ce_type { Flow_ce, Speed_ce }; // Flow and Speed controlled events + +enum breakpoint_type { at_bp, every_bp }; // Flow and Speed controlled events + + +//====================================================================================// +// User Preferences Defaults // +//====================================================================================// + +const int def_verbose = 1; // Verbose mode +const double def_time = 1.0 ; // Maximum simulation time +const double def_err = 1e-5; // Minimum error +const double def_thresh = close_to_zero; // Threshold +const simuleau_name def_length_unity = "km"; // Length unity +const simuleau_name def_time_unity = "h"; // Time unity + +//====================================================================================// +// Includes Simuleau Classes Error Codes // +//====================================================================================// +#include "bpn/bpn.h" // main BPN class (class BPN ) 1100 +#include "bpn/node.h" // node class (class Node ) 1200 +#include "bpn/place.h" // place classes (class Place, DiscretePlace, + // ContinuousPlace, BatchPlace, + // TriangularBatchPlace ) 1300 +#include "bpn/transition.h" // transition classes (class Transition, + // DiscreteTransition, + // ContinuousTransition, + // BatchTransition ) 1400 +#include "bpn/arc.h" // arc class (class Arc ) 1500 +#include "bpn/batch.h" // batch classes (class Batch, TriangularBatch) 1600 +#include "bpn/flow.h" // flow class (class Flow ) 1700 +#include "bpn/firingquantity.h" // firingquantity class + +#include "simul/event.h" // event classes (class Event, ExternalEvent ) 1800 +#include "simul/breakpoint.h" // event classes (class Event, ExternalEvent ) 1850 +#include "simul/schedule.h" // schedule class (class Schedule ) 1900 +#include "simul/simtime.h" // simtime class (class Simtime ) 2000 +#include "simul/simulate.h" // simulate class (class Simulate ) 2100 + + +//====================================================================================// +// Includes Simuleau Packages Error Codes // +//====================================================================================// +#include "interf/interf.h" // user interface package for UNIX version 6200 +#include "interf/prf.h" // user preferences (class PRF) 6100 +#include "interf/timer.h" // timer definitions package (timer.C from pac++) + + +#endif // SIMULEAU_H -- GitLab