Evolife
Evolife has been developed to study Genetic algorithms, Natural evolution and behavioural ecology.
Alliances.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2""" @brief Individuals inherit this class which determines who is friend with whom.
3"""
4
5#============================================================================#
6# EVOLIFE http://evolife.telecom-paris.fr Jean-Louis Dessalles #
7# Telecom Paris 2022-04-11 www.dessalles.fr #
8# -------------------------------------------------------------------------- #
9# License: Creative Commons BY-NC-SA #
10#============================================================================#
11# Documentation: https://evolife.telecom-paris.fr/Classes #
12#============================================================================#
13
14
15
18
19
20import sys
21if __name__ == '__main__': sys.path.append('../..') # for tests
22
23
24from Evolife.Tools.Tools import error
25
26class club:
27 """ class club: list of individuals associated with their performance.
28 The performance is used to decide who gets acquainted with whom.
29 """
30
31 def __init__(self, sizeMax = 0):
32 """ initializes club as an empty list of couples (individual,performance)
33 """
34 self.sizeMax = sizeMax
35 if sizeMax == 0:
36 self.sizeMax = sys.maxsize
37 self.reset()
38
39 def reset(self):
40 self.__members = [] # list of couples (individual,performance)
41
42 # def members(self): return self.__members
43
44 def names(self):
45 """ returns members' names (first elements of couples stored in members)
46 """
47 return [T[0] for T in self]
48
49 def performances(self):
50 """ returns members' performances (second elements of couples stored in members)
51 """
52 return [T[1] for T in self]
53
54 def present(self, MemberPerf):
55 """ returns True if the couple MemberPerf belongs to the club
56 """
57 return MemberPerf in self
58
59 def ordered(self, ordered=True):
60 """ returns a list of members names (possibly ordered by decreasing performance)
61 """
62 if ordered:
63 return [T[0] for T in sorted(self.__members, key = lambda x: x[1], reverse=True)]
64 return [T[0] for T in self]
65
66 def rank(self, Member):
67 """ returns the rank of Member in the list of decreasing performances
68 """
69 try: return self.ordered().index(Member)
70 except ValueError: return -1
71
72 def performance(self, Member):
73 """ returns the performance of Member
74 """
75 try: return self.__members[self.names().index(Member)][1]
76 except ValueError: error('Alliances', 'Searching for non-member')
77
78 def size(self):
79 """ size of the club
80 """
81 return len(self.__members)
82
83 def minimal(self):
84 """ returns the minimal performance among members
85 """
86 if self.size(): return min([T[1] for T in self])
87 return -1
88
89 def maximal(self):
90 """ returns the maximal performance among members
91 """
92 if self.size(): return max([T[1] for T in self])
93 return -1
94
95 def best(self):
96 """ returns the member with the best performance
97 """
98 # if self.size(): return self.ordered()[0]
99 # if self.size(): return max([T for T in self.__members], key=lambda x: x[1])[0]
100 if self.size(): return max(self, key=lambda x: x[1])[0]
101 return None
102
103 def worst(self):
104 """ returns the member with the worst performance
105 """
106 if self.size(): return self.ordered()[-1]
107 return None
108
109 def accepts(self, performance, conservative=True):
110 """ Checks whether an individual with 'performance' can be accepted into the club
111 Always true if club is not full.
112 Returns admission rank.
113 """
114 if self.size() >= self.sizeMax:
115 if conservative and performance <= self.minimal():
116 return -1 # equality: priority given to former members
117 elif performance < self.minimal(): return -1
118 # returning the rank that the candidate would be assigned
119 # return sorted([performance] + self.performances(),reverse=True).index(performance)
120 rank = self.size() - sorted([performance] + self.performances()).index(performance)
121 if rank <= self.sizeMax: return rank
122 error('Alliances', 'accept')
123
124 def enters(self, newMember, performance, conservative=True):
125 """ If newMember is accepted based on its performance, it enters the club.
126 If too many members in the club, the worst one is ejected and returned
127 """
128 if self.accepts(performance, conservative=conservative) >= 0:
129 # First, check whether newMember is not already a member
130 if newMember in self.names():
131 self.exits(newMember) # to prepare the come-back
132 if self.size() >= self.sizeMax:
133 worst = self.worst() # the redundant individual will be ejected
134 else: worst = None
135 self.__members.append((newMember, performance))
136 return worst
137 error("Alliances: unchecked admittance")
138 return None
139
140 def exits(self, oldMember):
141 """ a member goes out from the club
142 """
143 for (M,Perf) in self.__members[:]: # safe to copy the list as it is changed within the loop
144 if M == oldMember:
145 self.__members.remove((oldMember,Perf))
146 return True
147 print('exiled: %s' % str(oldMember))
148 error('Alliances: non-member attempting to quit a club')
149 return False
150
151 def weakening(self, Factor = 0.9): # temporary value
152 """ all performances are reduced (represents temporal erosion)
153 """
154 for (M,Perf) in self.__members[:]: # safe to copy the list as it is changed within the loop
155 self.__members.remove((M, Perf))
156 self.__members.append((M, Perf * Factor))
157
158 def __iter__(self): return iter(self.__members)
159
160 def __len__(self): return len(self.__members)
161
162 def __str__(self):
163 # return "[" + '-'.join([T.ID for T in self.ordered()]) + "]"
164 return "[" + '-'.join([str(T) for T in self.names()]) + "]"
165
166class Friend:
167 """ class Friend: defines an individual's acqaintances
168 """
169
170 def __init__(self, MaxFriends=1):
171 """ Defines Friend as a club
172 """
173 self.friends = club(MaxFriends)
174
175
178 def accepts(self, F_perf):
179 """ Checks whether an individual with 'performance' can be accepted as a friend.
180 Returns admission rank
181 """
182 return self.friends.accepts(F_perf)
183
184 def affiliable(self, F_perf, conservative=True):
185 """ Checks whether affiliation is possible
186 """
187 return self.friends.accepts(F_perf, conservative=conservative) >= 0
188
189 def follow(self, F, F_perf, conservative=True, Quit=None):
190 """ the individual wants to be F's disciple due to F's performance
191 """
192 # print self.ID, "wants to follows", (F.ID, F_perf)
193 if self.affiliable(F_perf, conservative=conservative):
194 # the new friend is good enough
195 RF = self.friends.enters(F, F_perf, conservative=conservative) # returns ejected old friend
196 if RF is not None:
197 # print('redundant friend of %s: %s' % (self, RF))
198 # print('self: %s' % self, ">>> self's friends: %s " % map(str, Friend.social_signature(self)))
199 if Quit is None: Quit = self.quit_
200 Quit(RF) # some redundant friend is disowned
201 return True
202 else: return False
203
204 def follows(self, Friend):
205 """ checks whether Friend belongs to actual friends
206 """
207 return Friend in self.names()
208 # R = Friend in self.friends.names()
209 # if R: print self.ID, 'is already following', Friend.ID
210
211 def quit_(self, Friend=None):
212 """ the individual no longer follows its friend
213 """
214 if Friend is None: Friend = self.friends.worst()
215 if Friend is not None:
216 # print(self, 'quits ', Friend)
217 self.friends.exits(Friend)
218
219 def best_friend(self): return self.friends.best()
220
221 def Max(self): return max(0, self.friends.maximal())
222
223 def Friends(self, ordered=True):
224 """ returns a list of friend names (possibly ordered by decreasing performance)
225 """
226 return self.friends.ordered(ordered=ordered)
227
228 def names(self):
229 """ returns the list of friends' names
230 """
231 return self.friends.ordered(ordered=False)
232
233 def rank(self, Friend):
234 """ returns the rank of Friend in the list of decreasing performances
235 """
236 return self.friends.rank(Friend)
237
238 def nbFriends(self):
239 """ Number of friends
240 """
241 return self.friends.size()
242
243 def size(self):
244 """ Number of friends
245 """
246 return self.friends.size()
247
248 def sizeMax(self): return self.friends.sizeMax
249
250 def lessening_friendship(self, Factor=0.9):
251 """ all performances are reduced (represents temporal erosion)
252 """
253 self.friends.weakening(Factor)
254
255 def checkNetwork(self, membershipFunction=None):
256 """ updates links by forgetting friends that are gone
257 """
258 for F in self:
259 if not membershipFunction(F): self.quit_(F)
260
261 def detach(self):
262 """ The individual quits all its friends
263 """
264 for F in self: self.quit_(F)
265
266
269 def acquaintable(self, Offer, Partner, PartnerOffer):
270 """ Checks that self and Partner would accept each other as friend, based on their performance
271 """
272 return self.affiliable(PartnerOffer) and Partner.affiliable(Offer)
273
274 def get_friend(self, Offer, Partner, PartnerOffer):
275 """ Checks mutual acceptance and then establishes friendship
276 """
277 if self.acquaintable(Offer, Partner, PartnerOffer):
278 if not self.follow(Partner, PartnerOffer, Quit=self.end_friendship):
279 error("Friend: self changed mind")
280 if not Partner.follow(self, Offer, Quit=Partner.end_friendship):
281 error("Friend: Partner changed mind")
282 return True
283 return False
284
285 def acquainted(self, Partner):
286 """ same as get_friend/3 with no performance
287 """
288 return self.get_friend(0, Partner, 0)
289
290 def end_friendship(self, Partner):
291 """ Partners remove each other from their address book
292 """
293 # print('\nsplitting up', self.ID, Partner.ID)
294 self.quit_(Partner)
295 Partner.quit_(self)
296
297 def forgetAll(self):
298 """ The individual quits its friends
299 """
300 for F in self: self.end_friendship(F)
301
302 def __iter__(self): return iter(self.friends.names())
303
304 def __len__(self): return len(self.friends)
305
307 """ returns the ordered list of friends
308 """
309 # return [F.ID for F in self.friends.names()]
310 return self.friends.ordered()
311
312 def signature(self):
313 """ same as social_signature
314 """
315 return self.social_signature()
316
317 def __str__(self):
318 return str(self.friends)
319
321 """ Augmented version of Friends for asymmetrical links - replaces 'Alliances'.
322 'Follower' in addition knows about who is following self
323 """
324
325 def __init__(self, MaxGurus, MaxFollowers=0):
326 """ calls the Friend constructor for followees.
327 creates another Friend object for followers
328 """
329 Friend.__init__(self, MaxGurus)
330 if MaxFollowers:
331 self.followers = Friend(MaxFollowers) # 'Friend' used as a mirror class to keep track of followers
332 else: self.followers = None
333
334 def F_affiliable(self, perf, Guru, G_perf, conservative=True):
335 """ Checks whether affiliation is possible
336 by checking acceptance both in friends and in followers
337 """
338 A = self.affiliable(G_perf, conservative=conservative) # Guru is acceptable and ...
339 if self.followers is not None:
340 A &= Guru.followers.affiliable(perf, conservative=conservative) # ...self acceptable to Guru
341 return A
342
343 def F_follow(self, perf, G, G_perf, conservative=True):
344 """ the individual wants to be G's disciple because of some of G's performance
345 G may evaluate the individual's performance too
346 """
347 # print '.',
348 if self.F_affiliable(perf, G, G_perf, conservative=conservative):
349 # ------ the new guru is good enough and the individual is good enough for the guru
350 # print('%s (%s) is about to follow %s (%s)' % (self, list(map(str, self.social_signature())), G, list(map(str, G.social_signature()))))
351 if not self.follow(G, G_perf, conservative=conservative, Quit=self.G_quit_):
352 error("Alliances", "inconsistent guru")
353 if G.followers is not None:
354 if not G.followers.follow(self, perf, conservative=conservative, Quit=G.F_quit_):
355 error('Alliances', "inconsistent self")
356 # self.consistency()
357 # G.consistency()
358 return True
359 else: return False
360
361 def G_quit_(self, Guru):
362 """ the individual no longer follows its guru
363 """
364 # self.consistency()
365 # Guru.consistency()
366 self.quit_(Guru)
367 if Guru.followers is not None: Guru.followers.quit_(self)
368
369 def F_quit_(self, Follower):
370 """ the individual does not want its disciple any longer
371 """
372 if self.followers is not None:
373 self.followers.quit_(Follower)
374 Follower.quit_(self)
375 else: error('Alliances', 'No Follower whatsoever')
376
377 def get_friend(self, Offer, Partner, PartnerOffer):
378 """ Checks mutual acceptance and then establishes friendship
379 """
380 if self.acquaintable(Offer, Partner, PartnerOffer):
381 if not self.F_follow(Offer, Partner, PartnerOffer):
382 error("Friend: self changed mind")
383 if not Partner.F_follow(PartnerOffer, self, Offer):
384 error("Friend: Partner changed mind")
385 return True
386 return False
387
388 def end_friendship(self, Partner):
389 """ Partners remove each other from their address book
390 """
391 # print('\nsplitting up', self.ID, Partner.ID)
392 # print(self.consistency(), Partner.consistency())
393 self.G_quit_(Partner)
394 Partner.G_quit_(self)
395
396 def nbFollowers(self): return self.followers.nbFriends()
397
398 def follower_rank(self, Friend):
399 """ Returns Friend's rank among self's followers
400 """
401 if self.followers: return self.followers.rank(Friend)
402 return -1
403
404 def forgetAll(self):
405 """ calls 'detach' for self's followers and then for self.
406 """
407 if self.followers is None: Friend.forgetAll(self)
408 else: self.detachdetach()
409
410 def detach(self):
411 """ The individual quits its guru and quits its followers
412 """
413 for G in self.names(): self.G_quit_(G) # G is erased from self's guru list
414 if self.names() != []: error("Alliances: recalcitrant guru")
415 if self.followers is not None:
416 for F in self.followers.names(): self.F_quit_(F) # self is erased from F's guru list
417 if self.followers.names() != []: error("Alliances: sticky followers")
418
419 def consistency(self):
420 """ checks social links consistency (self belongs to the followers of its followees)
421 """
422 # if self.size() > self.sizeMax():
423 # error("Alliances", "too many gurus: %d" % self.friends.size())
424 # if self.followers.size() > self.followers.sizeMax():
425 # error("Alliances", "too many followers: %d" % self.followers.friends.size())
426 for F in self.followers:
427 if self not in F:
428 print('self: %s' % self)
429 print("self's followers: %s" % list(map(str, self.followers.names())))
430 print('follower: %s' % F)
431 print('its gurus: %s' % list(map(str, F.friends.names())))
432 error("Alliances: non following followers")
433 if self == F: error("Alliances: Narcissism")
434
435 for G in self:
436 if self not in G.followers:
437 print('\n\nself: %s' % self)
438 print("self's gurus: %s" % list(map(str, self.friends.names())))
439 print('guru: %s' % G)
440 print('its followers: %s' % list(map(str, G.followers.names())))
441 error("Alliances: unaware guru")
442 if self == G: error("Alliances: narcissism")
443
445 if self.friends.size() > 0:
446 if not self.friends.present((self.friends.best(), self.friends.maximal())):
447 error("Alliances: best guru is ghost")
448 return ('%s consistent' % self.ID)
449
450# # # # class Alliances(object):
451 # # # # """ class Alliances: each agent stores both its gurus and its followers
452 # # # # (This is an old class, kept for compatibility (and not tested) """
453
454 # # # # def __init__(self, MaxGurus, MaxFollowers):
455 # # # # self.gurus = Friend(MaxGurus)
456 # # # # self.followers = Friend(MaxFollowers)
457
458 # # # # #################################
459 # # # # # hierarchical links #
460 # # # # #################################
461
462 # # # # def affiliable(self, perf, Guru, G_perf, conservative=True):
463 # # # # " Checks whether affiliation is possible "
464 # # # # return self.gurus.affiliable(G_perf, conservative=conservative) \
465 # # # # and Guru.followers.affiliable(perf, conservative=conservative)
466
467 # # # # def follow(self, perf, G, G_perf, conservative=True):
468 # # # # """ the individual wants to be G's disciple because of some of G's performance
469 # # # # G may evaluate the individual's performance too
470 # # # # """
471 # # # # if self.affiliable(perf, G, G_perf, conservative=conservative):
472 # # # # # the new guru is good enough and the individual is good enough for the guru
473 # # # # self.gurus.follow(G, G_perf, conservative=conservative, Quit=self.quit_)
474 # # # # G.followers.follow(self, perf, conservative=conservative, Quit=G.quit_)
475 # # # # return True
476 # # # # else: return False
477
478 # # # # def quit_(self, Guru):
479 # # # # """ the individual no longer follows its guru
480 # # # # """
481 # # # # Guru.followers.quit_(self)
482 # # # # self.gurus.quit_(Guru)
483
484 # # # # def best_friend(self): return self.gurus.best_friend()
485
486 # # # # def friends(self, ordered=True): return self.gurus.Friends(ordered=ordered)
487
488 # # # # def nbFriends(self): return self.gurus.nbFriends()
489
490 # # # # def nbFollowers(self): return self.followers.nbFriends()
491
492 # # # # def lessening_friendship(self, Factor=0.9):
493 # # # # self.gurus.lessening_friendship(Factor)
494
495 # # # # def forgetAll(self):
496 # # # # self.gurus.forgetAll()
497 # # # # self.followers.forgetAll()
498
499 # # # # #################################
500 # # # # # symmetrical links #
501 # # # # #################################
502
503 # # # # def acquaintable(self, Partner, Deal):
504 # # # # return self.affiliable(Deal, Partner, Deal) and Partner.affiliable(Deal, self, Deal)
505
506 # # # # def get_friend(self, Offer, Partner, Return=None):
507 # # # # " Checks mutual acceptance before establishing friendship "
508 # # # # if Return is None: Return = Offer
509 # # # # if self.affiliable(Offer, Partner, Return) and Partner.affiliable(Return, self, Offer):
510 # # # # self.follow(Offer, Partner, Return)
511 # # # # Partner.follow(Return, self, Offer)
512 # # # # return True
513 # # # # return False
514
515 # # # # def best_friend_symmetry(self):
516 # # # # " Checks whether self is its best friend's friend "
517 # # # # BF = self.best_friend()
518 # # # # if BF: return self == BF.best_friend()
519 # # # # return False
520
521 # # # # def restore_symmetry(self):
522 # # # # " Makes sure that self is its friends' friend - Useful for symmmtrical relations "
523 # # # # for F in self.gurus.names()[:]: # need to copy the list, as it is modified within the loop
524 # # # # #print 'checking symmetry for %d' % F.ID, F.gurus.names()
525 # # # # if self not in F.gurus.names():
526 # # # # print('%s quits %s ***** because absent from %s' % (self.ID, F.ID, str(F.gurus.names())))
527 # # # # self.quit_(F) # no hard feelings
528
529
530 # # # # #################################
531 # # # # # link processing #
532 # # # # #################################
533 # # # # def detach(self):
534 # # # # """ The individual quits its guru and its followers
535 # # # # """
536 # # # # for G in self.gurus.names(): self.quit_(G)
537 # # # # for F in self.followers.names(): F.quit_(self)
538 # # # # if self.gurus.names() != []: error("Alliances: recalcitrant guru")
539 # # # # if self.followers.names() != []: error("Alliances: sticky followers")
540
541 # # # # def consistency(self):
542 # # # # if self.gurus.size() > self.gurus.sizeMax():
543 # # # # error("Alliances", "too many gurus: %d" % self.gurus.size())
544 # # # # if self.followers.size() > self.followers.sizeMax():
545 # # # # error("Alliances", "too many followers: %d" % self.followers.size())
546 # # # # for F in self.followers.names():
547 # # # # if self not in F.gurus.names():
548 # # # # error("Alliances: non following followers")
549 # # # # if self == F: error("Alliances: Narcissism")
550# # # # ## print self.ID, ' is in ', F.ID, "'s guru list: ", [G.ID for G in F.gurus.names()]
551 # # # # for G in self.gurus.names():
552 # # # # if self not in G.followers.names():
553 # # # # # print 'self: ',str(self), "self's gurus: ",Alliances.social_signature(self)
554 # # # # # print 'guru: ',str(G), 'its followers: ',[str(F) for F in G.followers.names()]
555 # # # # error("Alliances: unaware guru")
556 # # # # if self == G: error("Alliances: narcissism")
557# # # # ## print self.ID, ' is in ', G.ID, "'s follower list: ", [F.ID for F in G.followers.names()]
558# # # # ## print '\t', self.ID, ' OK'
559 # # # # if self.gurus.size() > 0:
560 # # # # if not self.gurus.friends.present((self.gurus.best(), self.gurus.friends.maximal())):
561 # # # # error("Alliances: best guru is ghost")
562
563 # # # # def social_signature(self):
564# # # # ## return [F.ID for F in self.gurus.names()]
565 # # # # return self.gurus.Friends()
566
567 # # # # def signature(self): return self.social_signature()
568
569
572
573if __name__ == "__main__":
574 print(__doc__ + '\n')
575 print(Friend.__doc__ + '\n\n')
576 raw_input('[Return]')
577
578
579__author__ = 'Dessalles'
Augmented version of Friends for asymmetrical links - replaces 'Alliances'.
Definition: Alliances.py:320
def follower_rank(self, Friend)
Returns Friend's rank among self's followers.
Definition: Alliances.py:398
def get_friend(self, Offer, Partner, PartnerOffer)
Checks mutual acceptance and then establishes friendship.
Definition: Alliances.py:377
def end_friendship(self, Partner)
Partners remove each other from their address book.
Definition: Alliances.py:388
def G_quit_(self, Guru)
the individual no longer follows its guru
Definition: Alliances.py:361
def consistency(self)
checks social links consistency (self belongs to the followers of its followees)
Definition: Alliances.py:419
def F_quit_(self, Follower)
the individual does not want its disciple any longer
Definition: Alliances.py:369
def F_affiliable(self, perf, Guru, G_perf, conservative=True)
Checks whether affiliation is possible by checking acceptance both in friends and in followers.
Definition: Alliances.py:334
def F_follow(self, perf, G, G_perf, conservative=True)
the individual wants to be G's disciple because of some of G's performance G may evaluate the individ...
Definition: Alliances.py:343
def forgetAll(self)
calls 'detach' for self's followers and then for self.
Definition: Alliances.py:404
def detach(self)
The individual quits its guru and quits its followers.
Definition: Alliances.py:410
class Friend: defines an individual's acqaintances
Definition: Alliances.py:166
def forgetAll(self)
The individual quits its friends
Definition: Alliances.py:297
def get_friend(self, Offer, Partner, PartnerOffer)
Checks mutual acceptance and then establishes friendship.
Definition: Alliances.py:274
def acquaintable(self, Offer, Partner, PartnerOffer)
symmetrical links #
Definition: Alliances.py:269
def affiliable(self, F_perf, conservative=True)
Checks whether affiliation is possible.
Definition: Alliances.py:184
def follows(self, Friend)
checks whether Friend belongs to actual friends
Definition: Alliances.py:204
def __init__(self, MaxFriends=1)
Defines Friend as a club.
Definition: Alliances.py:170
def quit_(self, Friend=None)
the individual no longer follows its friend
Definition: Alliances.py:211
def lessening_friendship(self, Factor=0.9)
all performances are reduced (represents temporal erosion)
Definition: Alliances.py:250
def accepts(self, F_perf)
asymmetrical links #
Definition: Alliances.py:178
def nbFriends(self)
Number of friends.
Definition: Alliances.py:238
def rank(self, Friend)
returns the rank of Friend in the list of decreasing performances
Definition: Alliances.py:233
def signature(self)
same as social_signature
Definition: Alliances.py:312
def names(self)
returns the list of friends' names
Definition: Alliances.py:228
def detach(self)
The individual quits all its friends
Definition: Alliances.py:261
def checkNetwork(self, membershipFunction=None)
updates links by forgetting friends that are gone
Definition: Alliances.py:255
def end_friendship(self, Partner)
Partners remove each other from their address book.
Definition: Alliances.py:290
def social_signature(self)
returns the ordered list of friends
Definition: Alliances.py:306
def acquainted(self, Partner)
same as get_friend/3 with no performance
Definition: Alliances.py:285
def Friends(self, ordered=True)
returns a list of friend names (possibly ordered by decreasing performance)
Definition: Alliances.py:223
def size(self)
Number of friends.
Definition: Alliances.py:243
def follow(self, F, F_perf, conservative=True, Quit=None)
the individual wants to be F's disciple due to F's performance
Definition: Alliances.py:189
class club: list of individuals associated with their performance.
Definition: Alliances.py:26
def best(self)
returns the member with the best performance
Definition: Alliances.py:95
def exits(self, oldMember)
a member goes out from the club
Definition: Alliances.py:140
def minimal(self)
returns the minimal performance among members
Definition: Alliances.py:83
def present(self, MemberPerf)
returns True if the couple MemberPerf belongs to the club
Definition: Alliances.py:54
def performances(self)
returns members' performances (second elements of couples stored in members)
Definition: Alliances.py:49
def accepts(self, performance, conservative=True)
Checks whether an individual with 'performance' can be accepted into the club Always true if club is ...
Definition: Alliances.py:109
def weakening(self, Factor=0.9)
all performances are reduced (represents temporal erosion)
Definition: Alliances.py:151
def worst(self)
returns the member with the worst performance
Definition: Alliances.py:103
def size(self)
size of the club
Definition: Alliances.py:78
def rank(self, Member)
returns the rank of Member in the list of decreasing performances
Definition: Alliances.py:66
def enters(self, newMember, performance, conservative=True)
If newMember is accepted based on its performance, it enters the club.
Definition: Alliances.py:124
def names(self)
returns members' names (first elements of couples stored in members)
Definition: Alliances.py:44
def performance(self, Member)
returns the performance of Member
Definition: Alliances.py:72
def maximal(self)
returns the maximal performance among members
Definition: Alliances.py:89
def ordered(self, ordered=True)
returns a list of members names (possibly ordered by decreasing performance)
Definition: Alliances.py:59
Various functions.
Definition: Tools.py:1
def error(ErrMsg, Explanation='')
Definition: Tools.py:182