2""" @brief  Individuals inherit this class which determines who is friend with whom.
 
    5#============================================================================# 
    6# EVOLIFE  http://evolife.telecom-paris.fr             Jean-Louis Dessalles   
   21if __name__ == 
'__main__':  sys.path.append(
'../..')  
 
   27    """ class club: list of individuals associated with their performance. 
   28        The performance is used to decide who gets acquainted 
with whom.
 
   31    def __init__(self, sizeMax = 0): 
   32        """ initializes club as an empty list of couples (individual,performance) 
   45        """ returns members' names (first elements of couples stored in members) 
   47        return [T[0] 
for T 
in self]
 
   50        """ returns members' performances (second elements of couples stored in members) 
   52        return [T[1] 
for T 
in self]
 
   55        """ returns True if the couple MemberPerf belongs to the club 
   57        return MemberPerf 
in self
 
   60        """ returns a list of members names  (possibly ordered by decreasing performance) 
   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]
 
   67        """ returns the rank of Member in the list of decreasing performances 
   69        try:    
return self.
ordered().index(Member)
 
   70        except ValueError:  
return -1
 
   73        """ returns the performance of Member 
   76        except ValueError:  
error(
'Alliances', 
'Searching for non-member')
 
   84        """ returns the minimal performance among members 
   86        if self.
size(): 
return min([T[1] 
for T 
in self])
 
   90        """ returns the maximal performance among members 
   92        if self.
size(): 
return max([T[1] 
for T 
in self])
 
   96        """ returns the member with the best performance 
  100        if self.
size(): 
return max(self, key=
lambda x: x[1])[0]
 
  104        """ returns the member with the worst performance  
  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.
 
  115            if conservative 
and performance <= self.
minimal():
 
  117            elif performance < self.
minimal():  
return -1
 
  120        rank = self.
size() - sorted([performance] + self.
performances()).index(performance)
 
  121        if rank <= self.
sizeMax:    
return rank
 
  122        error(
'Alliances', 
'accept')
 
  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
 
  128        if self.
accepts(performance, conservative=conservative) >= 0:
 
  130            if newMember 
in self.
names():
 
  131                self.
exits(newMember)   
 
  135            self.
__members.append((newMember, performance))
 
  137        error(
"Alliances: unchecked admittance")
 
  141        """ a member goes out from the club  
  147        print(
'exiled: %s' % str(oldMember))
 
  148        error(
'Alliances: non-member attempting to quit a club')
 
  152        """ all performances are reduced (represents temporal erosion)  
  156            self.
__members.append((M, Perf * Factor))
 
  164        return "[" + 
'-'.join([str(T) 
for T 
in self.
names()]) + 
"]" 
  167    """ class Friend: defines an individual's acqaintances  
  171        """ Defines Friend as a club 
  179        """ Checks whether an individual with 'performance' can be accepted as a friend. 
  180            Returns admission rank 
  185        """ Checks whether affiliation is possible  
  187        return  self.
friends.
accepts(F_perf, conservative=conservative) >= 0
 
  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 
  193        if self.
affiliable(F_perf, conservative=conservative):
 
  195            RF = self.
friends.enters(F, F_perf, conservative=conservative)  
 
  199                if Quit 
is None: Quit = self.
quit_ 
  205        """ checks whether Friend belongs to actual friends 
  207        return Friend 
in self.
names()
 
  212        """ the individual no longer follows its friend 
  214        if Friend 
is None: Friend = self.
friends.worst()
 
  215        if Friend 
is not None:
 
  224        """ returns a list of friend names  (possibly ordered by decreasing performance) 
  226        return self.
friends.ordered(ordered=ordered)
 
  229        """ returns the list of friends' names 
  231        return self.
friends.ordered(ordered=
False)
 
  234        """ returns the rank of Friend in the list of decreasing performances 
  239        """ Number of friends 
  244        """ Number of friends 
  248    def sizeMax(self):      
return self.friends.sizeMax
 
  251        """ all performances are reduced (represents temporal erosion)  
  256        """ updates links by forgetting friends that are gone  
  259            if not membershipFunction(F):   self.
quit_(F)
 
  262        """ The individual quits all its friends     
  264        for F 
in self:  self.
quit_(F)
 
  270        """ Checks that self and Partner would accept each other as friend, based on their performance 
  272        return self.
affiliable(PartnerOffer) 
and Partner.affiliable(Offer)
 
  275        """ Checks mutual acceptance and then establishes friendship  
  279                error(
"Friend: self changed mind")
 
  280            if not Partner.follow(self, Offer, Quit=Partner.end_friendship):
 
  281                error(
"Friend: Partner changed mind")
 
  286        """ same as get_friend/3 with no performance  
  291        """ Partners remove each other from their address book  
  298        """ The individual quits its friends     
  307        """ returns the ordered list of friends 
  313        """ same as social_signature 
  321    """ Augmented version of Friends for asymmetrical links - replaces 'Alliances'. 
  322        'Follower' in addition knows about who 
is following self
 
  325    def __init__(self, MaxGurus, MaxFollowers=0): 
  326        """ calls the Friend constructor for followees. 
  327            creates another Friend object for followers
 
  329        Friend.__init__(self, MaxGurus) 
  335        """ Checks whether affiliation is possible 
  336            by checking acceptance both in friends 
and in followers
 
  338        A = self.affiliable(G_perf, conservative=conservative)   
  340            A &= Guru.followers.affiliable(perf, conservative=conservative) 
 
  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 
  348        if self.
F_affiliable(perf, G, G_perf, conservative=conservative):
 
  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")
 
  362        """ the individual no longer follows its guru 
  367        if Guru.followers 
is not None:  Guru.followers.quit_(self)
 
  370        """ the individual does not want its disciple any longer 
  375        else:   
error(
'Alliances', 
'No Follower whatsoever')
 
  378        """ Checks mutual acceptance and then establishes friendship  
  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")
 
  389        """ Partners remove each other from their address book  
  394        Partner.G_quit_(self)
 
  399        """ Returns Friend's rank among self's followers 
  405        """ calls 'detach' for self's followers and then for self. 
  407        if self.
followers is None:  Friend.forgetAll(self)
 
  411        """ The individual quits its guru and quits its followers 
  414        if self.
names() != []:      
error(
"Alliances: recalcitrant guru")
 
  420        """ checks social links consistency (self belongs to the followers of its followees) 
  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")
 
  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")
 
  447                error(
"Alliances: best guru is ghost")
 
  448        return (
'%s consistent' % self.ID)
 
  573if __name__ == 
"__main__":
 
  574    print(__doc__ + 
'\n')
 
  575    print(Friend.__doc__ + 
'\n\n')
 
  576    raw_input(
'[Return]')
 
  579__author__ = 
'Dessalles' 
Augmented version of Friends for asymmetrical links - replaces 'Alliances'.
def follower_rank(self, Friend)
Returns Friend's rank among self's followers.
def get_friend(self, Offer, Partner, PartnerOffer)
Checks mutual acceptance and then establishes friendship.
def end_friendship(self, Partner)
Partners remove each other from their address book.
def G_quit_(self, Guru)
the individual no longer follows its guru
def consistency(self)
checks social links consistency (self belongs to the followers of its followees)
def F_quit_(self, Follower)
the individual does not want its disciple any longer
def F_affiliable(self, perf, Guru, G_perf, conservative=True)
Checks whether affiliation is possible by checking acceptance both in friends and in followers.
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...
def forgetAll(self)
calls 'detach' for self's followers and then for self.
def detach(self)
The individual quits its guru and quits its followers.
class Friend: defines an individual's acqaintances
def forgetAll(self)
The individual quits its friends
def get_friend(self, Offer, Partner, PartnerOffer)
Checks mutual acceptance and then establishes friendship.
def acquaintable(self, Offer, Partner, PartnerOffer)
symmetrical links #
def affiliable(self, F_perf, conservative=True)
Checks whether affiliation is possible.
def follows(self, Friend)
checks whether Friend belongs to actual friends
def __init__(self, MaxFriends=1)
Defines Friend as a club.
def quit_(self, Friend=None)
the individual no longer follows its friend
def lessening_friendship(self, Factor=0.9)
all performances are reduced (represents temporal erosion)
def accepts(self, F_perf)
asymmetrical links #
def nbFriends(self)
Number of friends.
def rank(self, Friend)
returns the rank of Friend in the list of decreasing performances
def signature(self)
same as social_signature
def names(self)
returns the list of friends' names
def detach(self)
The individual quits all its friends
def checkNetwork(self, membershipFunction=None)
updates links by forgetting friends that are gone
def end_friendship(self, Partner)
Partners remove each other from their address book.
def social_signature(self)
returns the ordered list of friends
def acquainted(self, Partner)
same as get_friend/3 with no performance
def Friends(self, ordered=True)
returns a list of friend names (possibly ordered by decreasing performance)
def size(self)
Number of friends.
def follow(self, F, F_perf, conservative=True, Quit=None)
the individual wants to be F's disciple due to F's performance
class club: list of individuals associated with their performance.
def best(self)
returns the member with the best performance
def exits(self, oldMember)
a member goes out from the club
def minimal(self)
returns the minimal performance among members
def present(self, MemberPerf)
returns True if the couple MemberPerf belongs to the club
def performances(self)
returns members' performances (second elements of couples stored in members)
def accepts(self, performance, conservative=True)
Checks whether an individual with 'performance' can be accepted into the club Always true if club is ...
def weakening(self, Factor=0.9)
all performances are reduced (represents temporal erosion)
def worst(self)
returns the member with the worst performance
def size(self)
size of the club
def rank(self, Member)
returns the rank of Member in the list of decreasing performances
def enters(self, newMember, performance, conservative=True)
If newMember is accepted based on its performance, it enters the club.
def names(self)
returns members' names (first elements of couples stored in members)
def performance(self, Member)
returns the performance of Member
def maximal(self)
returns the maximal performance among members
def ordered(self, ordered=True)
returns a list of members names (possibly ordered by decreasing performance)