This repository has been archived by the owner on Mar 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mas.py
299 lines (248 loc) · 7.6 KB
/
mas.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
#==================================================
# INFO-H-100 - Introduction à l'informatique
#
# Prof. Thierry Massart
# Année académique 2014-2015
#
# Projet: Système Multi-Agent (SMA)
#
#==================================================
import math
import random
import mas_environment as e
import mas_cell as c
import mas_population as p
import mas_agent as a
import mas_utils as u
#==================================================
# MAS
#==================================================
# --- Constants ---
MAX_IDX=7
ENV_IDX = 0 # Environment
POP_IDX = 1 # Agent population
CELL_RULES_IDX = 2 # List of rules applied on cells
AGENT_RULES_IDX = 3 # List of rules applied on agents
EXPERIMENT_ENDING_CONDITION_IDX = 4 # Function with the ending condition
MAX_CYCLE_IDX = 5 # Max number of cycles per experiment
CYCLE_IDX = 6 # Current cycle of an experiment
ORDER_ACTIVATION_IDX = 7 # Ordre d'activation des agents
# --- Default values ---
def DEFAULT_ENDING_CONDITION(mas):
# End experiment of the number of cycles reaches the defined maximum.
return (get_cycle(mas) >= get_max_cycle(mas) )
def new_ending_condition(mas):
"""
Fonction permettant d'arréter la simulation sous deux conditions:
- le nombre de cycl est égal au nombre de cycle maximal
- si plus aucun agent vivant ne subsiste
"""
alive_agents = p.size(get_pop(mas))
return (get_cycle(mas) >= get_max_cycle(mas) or alive_agents == 0)
# --- Private functions ---
# Note: These functions should not be called outside this module.
def __get_property(mas, property_idx):
# Return the value of the given property of the MAS.
if not (0 <= property_idx <= MAX_IDX):
raise Exception("Invalid MAS property index.")
return mas[property_idx]
def __set_property(mas, property_idx, value):
# Set the value of the given property of the MAS.
if not (0 <= property_idx <= MAX_IDX):
raise Exception("Invalid MAS property index.")
mas[property_idx] = value
def __empty_instance():
# Return an empty MAS instance.
return [None]*(MAX_IDX+1)
# --- Getters and setters ---
def get_env(mas):
"""
Return the environment of the MAS.
"""
return __get_property(mas, ENV_IDX)
def set_env(mas, env):
"""
Set the environment of the MAS.
"""
__set_property(mas, ENV_IDX, env)
def get_pop(mas):
"""
Return the agent population of the MAS.
"""
return __get_property(mas, POP_IDX)
def set_pop(mas, pop):
"""
Set the agent population of the MAS.
"""
__set_property(mas, POP_IDX, pop)
def get_cell_rules(mas):
"""
Return the cell rules of the MAS as a list of functions.
"""
return __get_property(mas, CELL_RULES_IDX)
def set_cell_rules(mas, rules_list):
"""
Set the cell rules of the MAS as a list of functions.
"""
__set_property(mas, CELL_RULES_IDX, rules_list)
def get_agent_rules(mas):
"""
Return the agent rules of the MAS as a list of functions.
"""
return __get_property(mas, AGENT_RULES_IDX)
def set_agent_rules(mas, rules_list):
"""
Set the agent rules of the MAS as a list of functions.
"""
__set_property(mas, AGENT_RULES_IDX, rules_list)
def get_ending_condition(mas):
"""
Return the ending condition function of the MAS.
"""
return __get_property(mas, EXPERIMENT_ENDING_CONDITION_IDX)
def set_ending_condition(mas, ending_condition_fn):
"""
Set the ending condition function of the MAS. The condition function
receives the MAS as parameter and returns a boolean to tell whether
or not to end the experiment.
"""
# Function signature: fn(mas) ---> boolean(end_experiment)
__set_property(mas, EXPERIMENT_ENDING_CONDITION_IDX, ending_condition_fn)
def get_max_cycle(mas):
"""
Return the maximum number of cycles for an experiment with the MAS.
"""
return __get_property(mas, MAX_CYCLE_IDX)
def set_max_cycle(mas, cycle):
"""
Set the maximum number of cycles for an experiment with the MAS.
"""
__set_property(mas, MAX_CYCLE_IDX, cycle)
def get_cycle(mas):
"""
Return the current cycle of an experiment.
"""
return __get_property(mas, CYCLE_IDX)
def set_cycle(mas, cycle):
"""
Set the current cycle of an experiment. This function should usually not
be called directly.
"""
__set_property(mas, CYCLE_IDX, cycle)
def set_order_activation(mas,order_activation):
__set_property(mas,ORDER_ACTIVATION_IDX,order_activation)
def get_order_activation(mas):
return __get_property(mas,ORDER_ACTIVATION_IDX)
# --- Initialisation ---
def new_instance():
"""
Return a new MAS instance.
"""
mas = __empty_instance()
set_env(mas, None)
set_pop(mas, None)
set_cell_rules(mas, [])
set_agent_rules(mas, [])
set_ending_condition(mas, DEFAULT_ENDING_CONDITION)
set_max_cycle(mas, 0)
set_cycle(mas, 0)
return mas
def new_instance_from_config(config):
"""
Return a new MAS instance that has been initialised according
to the parameters passed by the configuration.
"""
mas = new_instance()
# Environment
env = e.new_instance(mas, config)
set_env(mas, env)
env_capacity_distribs = u.cfg_capacity_distributions(config)
for distrib in env_capacity_distribs:
e.add_capacity_from_string(env,distrib)
# Agent population
pop = p.new_instance(mas, config)
set_pop(mas, pop)
# Cell rules
cell_rules = u.cfg_cell_rules(config)
for rule in cell_rules:
add_cell_rule_from_string(mas,rule)
# Agent rules
agent_rules = u.cfg_agent_rules(config)
for rule in agent_rules:
add_agent_rule_from_string(mas,rule)
# Experiment settings
set_max_cycle(mas,u.cfg_max_cycle(config))
set_ending_condition(mas,u.cfg_ending_condition(config))
set_order_activation(mas,u.cfg_order_activation(config))
return mas
# --- Environment rules ---
def add_cell_rule(mas, cell_rule):
"""
Add a cell rule to the MAS.
"""
mas[CELL_RULES_IDX].append(cell_rule)
def add_cell_rule_from_string(mas, cell_rule_str):
"""
Add a cell rule to the MAS based on a string
that represents the function call.
"""
add_cell_rule(mas, eval("c."+cell_rule_str))
def apply_cell_rules(mas):
"""
Apply all cell rules to each cell of the MAS's environment.
"""
env = get_env(mas)
for cell_rule in get_cell_rules(mas):
e.apply_fn_to_all_cells(env, cell_rule)
# --- Agent rules ---
def add_agent_rule(mas, agent_rule):
"""
Add an agent rule to the MAS.
"""
mas[AGENT_RULES_IDX].append(agent_rule)
def add_agent_rule_from_string(mas, agent_rule_str):
"""
Add an agent rule to the MAS based on a string
that represents the function call.
"""
add_agent_rule(mas, eval("a."+agent_rule_str))
def apply_agent_rules(mas):
"""
Apply all agent rules to each agent of the MAS's population.
"""
pop = get_pop(mas)
eval("p."+get_order_activation(mas)+"(pop)")
for agent_rule in get_agent_rules(mas):
p.apply_rule(pop, agent_rule)
# --- Execution ---
def increment_cycle(mas):
"""
Increment the cycle of the MAS by one unit.
"""
set_cycle(mas, get_cycle(mas)+1)
def run_one_cycle(mas):
"""
Run one experiment cycle of the MAS.
"""
apply_cell_rules(mas)
apply_agent_rules(mas)
def run_experiment(mas):
"""
Run a experiment on the initialised MAS.
"""
set_cycle(mas, 0)
ending_condition = get_ending_condition(mas)
while not eval(ending_condition+"(mas)"):
run_one_cycle(mas)
increment_cycle(mas)
# --- Terminal output ---
def show(mas):
"""
Print a description of the complete MAS as text.
"""
env = get_env(mas)
pop = get_pop(mas)
print("**** ENVIRONMENT ****")
e.show(env)
print("**** POPULATION ****")
p.show(pop)