-
Notifications
You must be signed in to change notification settings - Fork 0
/
ProyectoF.py
299 lines (268 loc) · 10.2 KB
/
ProyectoF.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
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
from mesa import Agent, Model
import random
from mesa.space import MultiGrid
from mesa.time import SimultaneousActivation
from mesa.datacollection import DataCollector
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
plt.rcParams["animation.html"] = "jshtml"
matplotlib.rcParams['animation.embed_limit'] = 2**128
import numpy as np
import pandas as pd
import time
import datetime
import random
used_ids = []
total_movements = 0
def get_grid(model):
'''
Esta es una función auxiliar que nos permite guardar el grid para cada uno de los agentes.
param model: El modelo del cual optener el grid.
return una matriz con la información del grid del agente.
'''
grid = np.zeros((model.grid.width, model.grid.height))
for cell in model.grid.coord_iter():
cell_content, pos = cell
if isinstance(cell_content, list):
banqueta = next((agent for agent in cell_content if isinstance(agent, Banqueta)), None)
auto = next((agent for agent in cell_content if isinstance(agent, Auto)), None)
if banqueta:
grid[pos[0]][pos[1]] = 1
elif auto:
grid[pos[0]][pos[1]] = 2
return grid
class Auto(Agent):
"""An agent that moves towards two target coordinates."""
def __init__(self, pos, model, unique_id, target1, target2):
# Pass the parameters to the parent class.
super().__init__(pos, model)
self.wait_steps = 0
# Create the agent's variables and set the initial values.
self.target1 = target1
self.target2 = target2
self.at_target1 = False
self.pos = pos
print(self.pos)
if pos == (31, 16):
self.target1 = (15,16)
self.target2 = (15,0)
if pos == (31,17):
self.target1 = (1,17)
self.target2 = (0,17)
if pos == (31,18):
self.target1= (1, 18)
self.target2= (0,18)
if pos == (19,0):
self.target1 = (19,12)
self.target2 = (31,12)
if pos == (16,0):
self.target1 = (16,16)
self.target2 = (0,16)
if pos == (17,0):
self.target1 = (17,1)
self.target2 = (17,31)
if pos == (18,0):
self.target1 = (18,1)
self.target2 = (18,31)
if pos == (0,12):
self.target1 = (12,12)
self.target2 = (12,0)
if pos == (0,15):
self.target1 = (16,15)
self.target2 = (16,31)
if pos == (0,13):
self.target1 = (1,13)
self.target2 = (31,13)
if pos == (0,14):
self.target1 = (1,14)
self.target2 = (31,14)
if pos == (12,31):
self.target1 = (12,19)
self.target2 = (0,19)
if pos == (15,31):
self.target1 = (15,15)
self.target2 = (31,15)
if pos == (13,31):
self.target1 = (13,30)
self.target2 = (13,0)
if pos == (14,31):
self.target1 = (14,30)
self.target2 = (14,0)
global used_ids
random_id = random.randint(1, 1000000) # You can change the range of random numbers as you wish
while random_id in used_ids:
random_id = random.randint(1, 1000000) # Generate another random number until it is not in the used_ids list
used_ids.append(random_id) # Add the random number to the used_ids list
self.unique_id = random_id
def step(self):
# Check if the agent has reached the first target
if self.pos is None:
return
if self.wait_steps > 0:
self.wait_steps -= 2
return
if not self.at_target1:
# Move towards the first target
new_pos = self.move_towards(self.target1)
# Check if there is another car agent two blocks away in the current direction
x, y = self.pos
nx, ny = new_pos
if x != nx:
next_pos = (nx + (nx - x), y)
else:
next_pos = (x, ny + (ny - y))
if new_pos == self.target1:
self.at_target1 = True
else:
# Move towards the second target
new_pos = self.move_towards(self.target2)
# Check if there is another car agent two blocks away in the current direction
x, y = self.pos
nx, ny = new_pos
if x != nx:
next_pos = (nx + (nx - x), y)
else:
next_pos = (x, ny + (ny - y))
if new_pos == self.target2:
self.model.grid.remove_agent(self)
return
if self.wait_steps > 0:
self.wait_steps -= 1
return
# Check if next_pos is within the grid boundaries
grid_width, grid_height = self.model.grid.width, self.model.grid.height
if 0 <= next_pos[0] < grid_width and 0 <= next_pos[1] < grid_height:
cellmates = self.model.grid.get_cell_list_contents([next_pos])
other_agents = [obj for obj in cellmates if isinstance(obj, Auto)]
if len(other_agents) == 0:
# Update the agent's position
self.model.grid.move_agent(self, new_pos)
global total_movements
total_movements += 1
def move_towards(self, target):
"""Move the agent one step closer to the target."""
x, y = self.pos
tx, ty = target
# Compute the new x coordinate
if x < tx:
x += 1
elif x > tx:
x -= 1
# Compute the new y coordinate
if y < ty:
y += 1
elif y > ty:
y -= 1
return (x, y)
class Banqueta(Agent):
def __init__(self, unique_id, model):
super().__init__(unique_id, model)
class CleanerModel(Model):
"""A model with some number of agents."""
def __init__(self, width, height, N, max_time, agent_positions):
self.num_agents = N
self.num_banquetas = 94
self.banquetas = []
self.grid = MultiGrid(width, height, True)
self.schedule = SimultaneousActivation(self)
self.max_time = max_time
self.start_time = time.time()
random.shuffle(agent_positions)
# Create Succ agents in cell (1,1) with unique IDs
counter = 0
for i in range(self.num_agents):
x, y = agent_positions[i]
a = Auto((x, y), self, counter, target1=(19, 19), target2=(19, 31))
counter += 1
self.grid.place_agent(a, (x, y))
self.schedule.add(a)
for i in range(self.num_banquetas):
banqueta = Banqueta(i, self)
if i < 12:
x = 0 + i
y = 11
self.grid.place_agent(banqueta, (x, y))
x = 20 + i
y = 11
self.grid.place_agent(banqueta, (x, y))
x = 0 + i
y = 20
self.grid.place_agent(banqueta, (x, y))
x = 20 + i
y = 20
self.grid.place_agent(banqueta, (x, y))
x = 11
y = 0 + i
self.grid.place_agent(banqueta, (x, y))
x = 11
y = 0 + i
self.grid.place_agent(banqueta, (x, y))
x = 20
y = 0 + i
self.grid.place_agent(banqueta, (x, y))
x = 11
y = 20 + i
self.grid.place_agent(banqueta, (x, y))
x = 20
y = 20 + i
self.grid.place_agent(banqueta, (x, y))
self.schedule.add(banqueta)
# Define the data collector to get the grid at each step
self.datacollector = DataCollector(
model_reporters={"Grid": get_grid})
def step(self):
'''
At each step, the data collector will collect the data defined and store the grid to be plotted later.
'''
# Check if the maximum execution time has been reached
agent_positions=[(31,19), (31,16) , (31,17), (31,18), (19,0), (16,0), (17,0), (18,0),(12,31), (13,31) , (14,31), (15,31), (0,12), (0,13), (0,14), (0,15)]
if time.time() - self.start_time > self.max_time:
return
if self.schedule.steps % 5 == 0:
x, y = agent_positions[random.randint(0, 15)]
a = Auto((x,y), self, counter, target1=(19, 19), target2=(19, 31))
self.grid.place_agent(a, (x,y))
self.schedule.add(a)
self.datacollector.collect(self)
self.schedule.step()
# Definimos el tamaño del Grid
GRID_SIZE = 32
# Definimos el número de generaciones a correr
duration = 20 # seconds
frame_rate = 5 # frames per second do not alter
num_frames = duration * frame_rate
num_agents = 6
max=1
agent_positions=[(31,19), (31,16) , (31,17), (31,18), (19,0), (16,0), (17,0), (18,0),(12,31), (13,31) , (14,31), (15,31), (0,12), (0,13), (0,14), (0,15)]
# Create an instance of CleanerModel with user-defined parameters
model = CleanerModel(GRID_SIZE, GRID_SIZE, num_agents, max, agent_positions)
# Record start time
start_time = time.time()
counter = 1
# Run simulation until maximum execution time is reached or all cells are clean
while True:
model.step()
counter += 1
if time.time() - model.start_time > model.max_time:
break
# Get data from simulation
all_grid = model.datacollector.get_model_vars_dataframe()
print("Total de movimientos realizados por todos los autos:", total_movements)
from matplotlib.colors import ListedColormap
# Create a custom colormap that maps 0 to white, 1 to black, and 2 to blue
cmap = ListedColormap(['white', 'black', 'blue'])
# Create the animation using the custom colormap
fig, axs = plt.subplots(figsize=(5,5))
axs.set_xticks([])
axs.set_yticks([])
patch = plt.imshow(all_grid.iloc[0][0], cmap=cmap)
def animate(i):
# Check if index is out-of-bounds
if i >= len(all_grid):
# If index is out-of-bounds, use last row of all_grid
i = len(all_grid) - 1
patch.set_data(all_grid.iloc[i][0])
anim = animation.FuncAnimation(fig, animate, frames=num_frames)
anim
plt.show()