forked from salabim/salabim
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDining philosophers animated.py
119 lines (93 loc) · 3.61 KB
/
Dining philosophers animated.py
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import salabim as sim
from math import sin, cos, radians
class AnimatePhilosopher(sim.Animate):
def __init__(self, i):
alpha = 360 / nphilosophers
r1 = 25
r2 = r1 * sin(radians(alpha) / 4)
angle = i * alpha
sim.Animate.__init__(self, x0=r1 * cos(radians(angle)), y0=r1 * sin(radians(angle)),
circle0=r2, linewidth0=0, xy_anchor='c')
self.i = i
def fillcolor(self, t):
if philosopher[self.i].mode() == 'eating':
return 'green'
if philosopher[self.i].mode() == 'thinking':
return 'fg'
return 'red'
class AnimateFork(sim.Animate):
def __init__(self, i):
alpha = 360 / nphilosophers
r1 = 25
r2 = r1 * sin(radians(alpha) / 4)
angle = (i + 0.5) * alpha
sim.Animate.__init__(self, x0=0, y0=0,
line0=(r1 - r2, 0, r1 + r2, 0), linewidth0=r2 / 4, linecolor0='green')
self.i = i
self.angle_mid = angle
self.angle_left = angle - 0.2 * alpha
self.angle_right = angle + 0.2 * alpha
def angle(self, t):
claimer = fork[self.i].claimers().head()
if claimer is None:
return self.angle_mid
if claimer == philosopher[self.i]:
return self.angle_left
return self.angle_right
def do_animation():
global nphilosophers, eatingtime_mean, thinkingtime_mean
global nphilosophers_last
env.animation_parameters(x0=-50 * env.width() / env.height(), y0=-50,
x1=+50 * env.width() / env.height(),
modelname='Dining philosophers',
speed=8, background_color='20%gray')
for i, _ in enumerate(philosopher):
AnimatePhilosopher(i=i)
AnimateFork(i=i)
sim.AnimateSlider(x=520, y=env.height(), width=100, height=20,
vmin=10, vmax=40, resolution=5, v=eatingtime_mean, label='eating time', action=set_eatingtime_mean)
sim.AnimateSlider(x=660, y=env.height(), width=100, height=20,
vmin=10, vmax=40, resolution=5, v=thinkingtime_mean, label='thinking time', action=set_thinkingtime_mean)
sim.AnimateSlider(x=520 + 50, y=env.height() - 50, width=200, height=20,
vmin=3, vmax=40, resolution=1, v=nphilosophers, label='# philosophers', action=set_nphilosophers)
nphilosophers_last = nphilosophers
def set_eatingtime_mean(val):
global eatingtime_mean
eatingtime_mean = float(val)
def set_thinkingtime_mean(val):
global thinkingtime_mean
thinkingtime_mean = float(val)
def set_nphilosophers(val):
global nphilosophers
global nphilosophers_last
nphilosophers = int(val)
if nphilosophers != nphilosophers_last:
nphilosophers_last = nphilosophers
env.main().activate()
class Philosopher(sim.Component):
def process(self):
while True:
thinkingtime = sim.Uniform(0.5, 1.5).sample() * thinkingtime_mean
eatingtime = sim.Uniform(0.5, 1.5).sample() * eatingtime_mean
yield self.hold(thinkingtime, mode='thinking')
yield self.request(self.leftfork, self.rightfork, mode='waiting')
yield self.hold(eatingtime, mode='eating')
self.release()
eatingtime_mean = 20
thinkingtime_mean = 20
nphilosophers = 8
sim.random_seed(1234567)
env = sim.Environment()
while True:
env.__init__()
philosopher = []
fork = []
for i in range(nphilosophers):
philosopher.append(Philosopher())
fork.append(sim.Resource('fork.'))
if i != 0:
philosopher[i].leftfork = fork[i - 1]
philosopher[i].rightfork = fork[i]
philosopher[0].leftfork = fork[nphilosophers - 1]
do_animation()
env.run(500)