From 1b108b118223689db310f9cb9b29653aedd55d68 Mon Sep 17 00:00:00 2001 From: SunYujia Date: Mon, 30 Jan 2023 14:26:29 +0800 Subject: [PATCH] version_initial --- fas_instance.py | 313 ++ fas可视化.py | 24 + faults/__init__.py | 0 faults/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 157 bytes .../__pycache__/retry_delay.cpython-311.pyc | Bin 0 -> 2024 bytes .../__pycache__/wear_and_tear.cpython-311.pyc | Bin 0 -> 1685 bytes faults/retry_delay.py | 31 + faults/wear_and_tear.py | 31 + output.json | 4082 +++++++++++++++++ 9 files changed, 4481 insertions(+) create mode 100644 fas_instance.py create mode 100644 fas可视化.py create mode 100644 faults/__init__.py create mode 100644 faults/__pycache__/__init__.cpython-311.pyc create mode 100644 faults/__pycache__/retry_delay.cpython-311.pyc create mode 100644 faults/__pycache__/wear_and_tear.cpython-311.pyc create mode 100644 faults/retry_delay.py create mode 100644 faults/wear_and_tear.py create mode 100644 output.json diff --git a/fas_instance.py b/fas_instance.py new file mode 100644 index 0000000..9d961b4 --- /dev/null +++ b/fas_instance.py @@ -0,0 +1,313 @@ +import salabim as sim +from numpy.random import normal +from faults.wear_and_tear import WearAndTear +from faults.retry_delay import RetryDelay + + +class ItemGenerator(sim.Component): + + def animation_objects(self, id): + if id == 'Item': + ao0 = sim.AnimateText(text=self.name(), textcolor='fg', text_anchor='nw') + return 0, 10, ao0 + else: + ao0 = sim.AnimateRectangle((-20, 0, 20, 20), + text=self.name(), fillcolor=id, textcolor='white', arg=self) + return 45, 0, ao0 + + def process(self): + for i in range(30): + # 设定为 30 items + # Clock() + Item() + print("item" + str(i) + " generated——————————") + yield self.hold(sim.Uniform(1, 2).sample()) + + +class Item(sim.Component): + def process(self): + self.enter(q) + yield self.request(crane) + Crane('Crane1', 30, logger) + yield self.request(Manual_Step) + ManualStep("MANUAL_INSPECTION", 37, logger).spawn() + yield self.request(conveyor) + Conveyor("CONVEYOR1", 30, logger).spawn() + yield self.request(Bowl_Feeder) + BowlFeeder("Bowl1", 30, logger) + ManualStep("MANUAL_ADD_COMPONENTS1", 21, logger) + Conveyor("CONVEYOR2", 30, logger) + # ————————添加retry delay故障—————————— + # self.bowl2 = BowlFeeder("BOWL2", 10, logger).add_fault(RetryDelay(BowlFeeder("BOWL2", 10, logger))) + BowlFeeder("BOWL2", 10, logger) + ManualStep("MANUAL_ADD_COMPONENTS2", 34, logger) + Conveyor("CONVEYOR3", 30, logger) + Crane("CRANE_INPUT_SUBASSEMBLY_A", 10, logger) + ManualStep("MANUAL_COMBINE_SUBASSEMBLY_A", 34, logger) + Conveyor("CONVEYOR4", 30, logger) + Conveyor("CONVEYOR_INPUT_SUBASSEMBLY_B", 10, logger) + ManualStep("MANUAL_COMBINE_SUBASSEMBLY_B", 35, logger) + # ———————— 添加磨损故障 ———————————— + # Conveyor("CONVEYOR5", 30, logger).add_fault(WearAndTear(Conveyor("CONVEYOR5", 30, logger))) + Conveyor("CONVEYOR5", 30, logger) + BowlFeeder("BOWL3", 5, logger) + Conveyor("CONVEYOR6", 10, logger) + ManualStep("MANUAL_ADD_COVER_AND_BOLTS", 76, logger) + Conveyor("CONVEYOR7", 30, logger) + ManualStep("MANUAL_TIGHTEN_BOLTS1", 28, logger) + Conveyor("CONVEYOR8", 30, logger) + Conveyor("CONVEYOR_INPUT_SUBASSEMBLY_C", 10, logger) + ManualStep("MANUAL_COMBINE_SUBASSEMBLY_C", 60, logger) + Conveyor("CONVEYOR9", 21, logger) + ManualStep("MANUAL_TIGHTEN_BOLTS2", 16, logger) + Conveyor("CONVEYOR10", 21, logger) + BowlFeeder("BOWL4", 5, logger) + ManualStep("MANUAL_ADD_COMPONENTS3", 11, logger) + Conveyor("CONVEYOR11", 21, logger) + ManualStep("MANUAL_TIGHTEN_BOLTS3", 32, logger) + self.leave(q) + # 添加leave语句时,与上述步骤同时开始执行,queue始终为0,不增;(不添加leave语句只增不减) + + +class BowlFeeder(sim.Component): + def __init__(self, name, duration, logger, debug=True): + super(BowlFeeder, self).__init__() + self.name = name + self.duration = duration + self.faults = [] + self.logger = logger + self.debug = debug + + def add_fault(self, fault): + self.faults.append(fault) + + def process(self): + if self.debug: + sim.waiting = "waiting" + waiting.set() + if self.debug: + print(self.name + ": give") + giving.set() + giving.trigger(max=1) + print(self.name + ": given") + yield self.hold(delay(self.duration, 1)) + self.logger.addMessage(self.name + " GIVEN") + self.release() + + def spawn(self): # 尝试修改return的结果后调用spawn 未发现明显变化 + self.process() + return self.passivate() + + def get_events(self): + return [self.name + " GIVEN"] + + +class ManualStep(sim.Component): + def __init__(self, name, duration, logger, debug=True): + super(ManualStep, self).__init__() + self.debug = debug + self.duration = duration + self.queue = 0 + self.logger = logger + self.name = name + + def process(self): + if self.debug: + print(self.name + ": input") + self.queue = self.queue + 1 + if (self.queue >= 5): + self.logger.addMessage(self.name + " QUEUE_ALARM") + if self.debug: + print(self.name + ": process") + running.set() + self.queue = self.queue - 1 + if self.debug: + print(self.name + ": ok") + if self.debug: + print(self.name + ": wait") + waiting.set() + yield self.hold(delay(self.duration, 5)) + self.logger.addMessage(self.name + " OK") + self.release() + + def spawn(self): + return self.process() + + def get_events(self): + return [self.name + " QUEUE_ALARM", self.name + " OK"] + + +class Crane(sim.Component): + def __init__(self, name, duration, logger, debug=True): + super(Crane, self).__init__() + self.debug = debug + self.duration = duration + self.queue = 0 + self.logger = logger + self.name = name + + def process(self): + if self.debug: + print(self.name + ": input") + # yield self.request(crane) + self.queue = self.queue + 1 + if self.debug: + print(self.name + ": go_forward") + self.logger.addMessage(self.name + " FORWARD") + yield self.hold(delay(self.duration, 1)) + self.release() + self.queue = self.queue - 1 + running.set() + if self.debug: + print(self.name + ": wait") + waiting.set() + if self.debug: + print(self.name + ": item_taken") + running.set() + print(self.name + ": go_back") + self.logger.addMessage(self.name + " BACKWARD") + yield self.hold(delay(self.duration, 1)) + print(self.name + ": stop") + self.logger.addMessage(self.name + " STOP") + self.passivate() + + def spawn(self): + return self.process() + + def get_events(self): + return [self.name + " FORWARD", self.name + " BACKWARD", + self.name + " STOP"] + + +class Conveyor(sim.Component): + def __init__(self, name, duration, logger, debug= True): + super(Conveyor, self).__init__() + self.name = name + self.duration = duration + self.faults = [] + self.logger = logger + self.debug = debug + + def add_fault(self, fault): + self.faults.append(fault) + + def process(self): + if self.debug: + waiting.set() + print(self.name + ": input") + self.logger.addMessage(self.name + " CONVEYOR_GATE") + giving.set() + giving.trigger(max=1) + if self.debug: + print(self.name + ": to_next_step") + # self.item = waitingline.pop() + # self.state = "giving" + yield delay(self.duration, 1) + for fault in self.faults: + yield fault.spawn() + + def spawn(self): # 没有找到合适的函数替代原本spawn函数 + return self.activate(process='process') + + def get_events(self): + return [self.name + " CONVEYOR_GATE"] + + +class Clock():# 未调用 + def __init__(self, env, logger, debug=True): + self.debug = debug + self.env= env + self.logger = logger + + def process(self): + print("Tick") + self.logger.addMessage("TICK") + yield 10 + + def spawn(self): + return self.process() + + def get_events(self): + return ["TICK"] + + +def delay(duration, percentage_variation): + stdev = percentage_variation / 100.0 * duration + random_additive_noise = normal(0, stdev) + return max(0, int(duration + random_additive_noise)) + + +class Logger: + """ This class logs all the messages. """ + def __init__(self,env): + self.env = env + self.loglines = [] + + def addMessage(self, type, metadata = ""): + logline = LogLine(self.env.now(), type, metadata) + self.loglines.append(logline) + + def indentLine(self, lineStr): + return " " + lineStr + + def indent(self, linesStr): + lines = linesStr.split("\n") + return "\n".join(map(self.indentLine, lines)) + + def getLoglines(self): + return "[\n" + (",\n".join(map(self.indent, map(str, self.loglines))) + "\n]\n") + + +class LogLine: + def __init__(self, timestamp, msgtype, metadata): + self.timestamp = timestamp + self.msgtype = msgtype + self.metadata = metadata + + def __str__(self): + return "{\n \"timestamp\": " + str(self.timestamp) + ",\n \"type\": \"" + self.msgtype + "\"\n}" + + +env = sim.Environment() +# env = sim.Environment(trace= True) + +giving = sim.State("giving") +waiting = sim.State("waiting") +running = sim.State("running") + +logger = Logger(env) +ItemGenerator() +# clock = Clock(env, logger) +# clock.spawn() # clock函数不显示 + +q = sim.Queue('queue') +env.background_color('20%gray') +Bowl_Feeder = sim.Resource("Bowl_Feeder", 1) +conveyor = sim.Resource("conveyor", 1) +crane = sim.Resource("crane", 1) +Manual_Step= sim.Resource("Manual_Step",1) +# 直接运行并存储 —————————————————————————————————————————————— +# env.run() +# print() +# q.print_statistics() +# f = open("output.json", "w") +# f.write(logger.getLoglines()) +# f.close() +# 可视化 ———————————————————————————————————————————————————— +qa0 = sim.AnimateQueue(q, x=100, y=250, title='queue, normal', direction='e', id='blue') +qa1 = sim.AnimateQueue(q, x=100, y=350, title='queue, maximum 6 components', direction='e', max_length=6, id='red') +qa2 = sim.AnimateQueue(q, x=100, y=150, title='queue, reversed', direction='e', reverse=True, id='green') + +sim.AnimateMonitor(q.length, x=10, y=450, width=480, height=100, horizontal_scale=3, vertical_scale=3) + +sim.AnimateMonitor(q.length_of_stay, x=10, y=570, width=480, height=100, horizontal_scale=5, vertical_scale=5) + +sim.AnimateText(text=lambda: q.length.print_histogram(as_str=True), x=500, y=750, + text_anchor='nw', font='narrow', fontsize=10) + +sim.AnimateText(text=lambda: q.print_info(as_str=True), x=500, y=340, + text_anchor='nw', font='narrow', fontsize=10) + +env.animate(True) +env.modelname('Demo queue animation') +env.run() \ No newline at end of file diff --git a/fas可视化.py b/fas可视化.py new file mode 100644 index 0000000..1c770e2 --- /dev/null +++ b/fas可视化.py @@ -0,0 +1,24 @@ +import salabim as sim +from fas复现.fas_instance import q +from fas复现.fas_instance import ItemGenerator + +env = sim.Environment() +ItemGenerator() +env.background_color('20%gray') +qa0 = sim.AnimateQueue(q, x=100, y=250, title='queue, normal', direction='e', id='blue') +qa1 = sim.AnimateQueue(q, x=100, y=350, title='queue, maximum 6 components', direction='e', max_length=6, id='red') +qa2 = sim.AnimateQueue(q, x=100, y=150, title='queue, reversed', direction='e', reverse=True, id='green') + +sim.AnimateMonitor(q.length, x=10, y=450, width=480, height=100, horizontal_scale=3, vertical_scale=3) + +sim.AnimateMonitor(q.length_of_stay, x=10, y=570, width=480, height=100, horizontal_scale=5, vertical_scale=5) + +sim.AnimateText(text=lambda: q.length.print_histogram(as_str=True), x=500, y=750, + text_anchor='nw', font='narrow', fontsize=10) + +sim.AnimateText(text=lambda: q.print_info(as_str=True), x=500, y=340, + text_anchor='nw', font='narrow', fontsize=10) + +env.animate(True) +env.modelname('Demo queue animation') +env.run() \ No newline at end of file diff --git a/faults/__init__.py b/faults/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/faults/__pycache__/__init__.cpython-311.pyc b/faults/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..22bc2363635968476dab98d6e79608e48a409310 GIT binary patch literal 157 zcmZ3^%ge<81UZu~Cxht6AOZ#$p^VRLK*n^26oz01O-8?!3`I;p{%4TnS6v|CVii-I zn3I^4nfr9@vL`zi#H1w_KV8!Myl(@LRhm;$91|a(nU`4-AFo$X`HRCQH$SB`C)KWq Z6{r_vMKM2+_`uA_$oPQ)Miemv#Q;)aC#e7c literal 0 HcmV?d00001 diff --git a/faults/__pycache__/retry_delay.cpython-311.pyc b/faults/__pycache__/retry_delay.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..81767fa237edabfb8fd11d06043b6099967f8a14 GIT binary patch literal 2024 zcmaJCT})e5_?+9`_EHK+$6rvgyRZjJ9J(hK!juV{CN3m0G+8CNx$C`M+uYt;&$*3j zQxjq^LpOAbAV`SAWI+g9#214s#=ZL1&c-!2+0%g0x0<@d_~dtPe*h(Z_w+mGJKuNC z_ka3bLxTqa41D!_aL|d+Q$|#QuPjP$!D1dMNWmHkV0-2Q4wyO38RG*yMjUz*DUKmZEtSvemS%K^U}`kg~Iijz3=CC9{jlX%bjOGJlOf> z#vYT_Kc4 zD?qK+c9v_aeHnySfLO0>V3g+4NUG^mFi=dR4QWPID+Fo-62OfTcCFuK@iYNZC5&we zk`&P+rX*RsqFzZ{wXkWqVuq5?RKL@5QdJ9)dJrUaOu9~z>|99_WvU>5lh0W-j0{Xr zS(C3sVmtR&wtrfl2+4Hk?##2#H(&)hq7!!dBs+b5@gx!8Q0mxzs`{#Cc!5FB0QzeZ zJrNpaq6;Up!ttDN{ISsUNa)E5y*Z&bBlPB5JExsDJ^5xIOs;&}OEA?>!&ic{D0m>y zh!uP{{7N0L`!>Q*xoH$-Vm2r^1v7-JLL+oAHPKosmTRG|3Btl;ajC$eTe%d3Z3Q&0 z*K7ez(9VkE2#zxa+4u;O7Of?XykIs|Z-!HR8XqnaC;+tV-j~>4!7VJlHbiUo{rkLv zL)?349^-O(xJC=i&;rw6V9C9@_%(xHUr)7MIQQQ|5xQ0P!iDA5kvQLgr(f_+NB|d z;=e+$HZ-2hg_l5qMzA(P@ey;2E#$dK_DAzdj@I$OO}$YfcGfa6Uq zx6;|B?u^iF8{o&|eu4G2F2_{pZI2|Cdm7eWN%|lmYZZ=Lk`yB-Np?pPcBQS+YN&L2 zP}MX^@?*jjQC1;CWxH6N*iQ&+FB%2}9b5g1oRb%dh#`-Y?_#T?k=M<2-83R7W29GS!hsEt$ik=xW1Y`G3)^W3ydC)eVA^K< E17B$EoB#j- literal 0 HcmV?d00001 diff --git a/faults/__pycache__/wear_and_tear.cpython-311.pyc b/faults/__pycache__/wear_and_tear.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e06dd3cb1c8717a46d4d5f3157d1c94febe3fa5 GIT binary patch literal 1685 zcmaJ>&2Jk;6rb4-dmXQx#!cK%(#p_qSVDUMq_hE{ScGz*@`0LGxRFL%&!%-)e=xgN z6XRAsRKip#1*uhn#KDKk6h%nA@?Y4luw-8ttb(wMD5BUzMV!N!%YrH7L;<~zsCW}m$q+ZC;9wgf z?Za=laxxXpBTYWws)k+B*s5gm{-(zQ*THL`ehya|D2FM^2~=*P4NQfbk(|h{$w^cK z3f3*03qjD38@*`gEM1~mVA*^SiHGIsaDC7Kau4q!8-w64TL>hC>ZlFc{>aiANzZ%` zYJ;*rGGJ5}>WGZ)qZqUi0Clbf@BvtmsgPkjEMzQO)r!Fw-*y#33Z;Tgh$~a$a`lRf zZ8uab)2eA`k}Fw;xxu2~$RgZ3LP*}!EsGF~UzJLw8c$ybVQppI(oOwxq4?y7_OCy- z);DzP$^F~Eefbcis%cy6*8m-&mngA8I91tZ3LLA=j$wBy$RrFq)@dMrHPB-vcKegP zH@ixzr=%V!+E0qsRhD|nQb$>G=8iU{ohfG~0W9Ps7l1{Z@C@KA%8y~~RpJB~2R{S( z0AZ+b9c^+qZ&6$W4v6_WLiPw(ZXfd$YJf%?V(*XQ!)a(?D)OD{m?OVAs^8`)P7UC` z4i$UWr0kH*k@Xjq>cV6fK!s5&6zq?4@SMot0^0RPf;V~QfG2ik=svr8a2%xC+}ZR; z=dvrQi|?gBB)z<2iaob`@G>x?L!jhUJzktWdID>1x@en#fe}b5&}X z`Zn3n^LClJQDe(yI`M24j{_~i;@mG>VdcDGS+&FCHTI1$@UT7u@;f{Y)K^dp7Dgd?XPt23R1_Ta6qy4+KjJL<9%PuwZoD(pqO@x@+zv7`8}qr{sbHVyYrbP2B- z|AxV