2""" @brief A basic framework to run social simulations.
7#============================================================================#
8# EVOLIFE http://evolife.telecom-paris.fr Jean-Louis Dessalles
18from random
import sample, randint, shuffle
22sys.path.append(
'../../..')
33 """ Global elements, mainly parameters
37 Parameters.Parameters.__init__(self, ConfigFile)
43 def Dump_(self, PopDump, ResultFileName, DumpFeatures, ExpeID, Verbose=False):
44 """ Saves parameter values, then agents' investment in signalling, then agents' distance to best friend
46 if Verbose: print(
"Saving data to %s.*" % ResultFileName)
47 SNResultFile = open(ResultFileName +
'_dmp.csv',
'w')
48 SNResultFile.write(
'%s\n' % ExpeID)
49 for Feature
in DumpFeatures:
50 SNResultFile.write(
";".join(PopDump(Feature)))
51 SNResultFile.write(
"\n")
58 """ Stores some global observation and display variables
62 """ Experiment_Observer constructor
63 + declaration of an average social distance curve
64 + initialization of social links
66 Observer.Experiment_Observer.__init__(self, Parameters)
69 if self.Parameter(
'AvgFriendDistance'):
70 self.curve(
'FriendDistance', Color=
'yellow', Legend=
'Avg distance to best friend')
74 """ Experiment_Observer's get_data + slot 'Network' that contains social links
76 if Slot ==
'Network':
return self.
Alliances
77 return Observer.Experiment_Observer.get_data(self, Slot, Consumption=Consumption)
80 """ The hot phase is a limited amount of time, controlled by the 'LearnHorizon' parameter,
81 during which learning is faster.
83 return self.StepId < self.TimeLimit * self.Parameter(
'LearnHorizon') / 100.0
86 """ A social individual has friends and can learn
89 def __init__(self, IdNb, features={}, maxQuality=100, parameters=None, SocialSymmetry=True):
90 """ Initalizes social links and learning parameters
92 if parameters: self.
Param = parameters.Param
93 else: self.
Param =
None
94 self.
ID =
"A%d" % IdNb
96 Alliances.Follower.__init__(self, self.
Param(
'MaxFriends'), self.
Param(
'MaxFriends'))
98 Alliances.Follower.__init__(self, self.
Param(
'MaxFriends'), self.
Param(
'MaxFollowers'))
99 self.
Quality = (100.0 * IdNb) / maxQuality
101 Learner.Learner.__init__(self, features, MemorySpan=self.
Param(
'MemorySpan'), AgeMax=self.
Param(
'AgeMax'),
102 Infancy=self.
Param(
'Infancy'), Imitation=self.
Param(
'ImitationStrength'),
103 Speed=self.
Param(
'LearningSpeed'), JumpProbability=self.
Param(
'JumpProbability', 0),
104 Conservatism=self.
Param(
'LearningConservatism'),
105 LearningSimilarity=self.
Param(
'LearningSimilarity'),
106 toric=self.
Param(
'Toric'), Start=self.
Param(
'LearningStart', default=-1))
111 """ called by Learner at initialization and when born again
112 Resets social links and learning experience
115 Learner.Learner.Reset(self, Newborn=Newborn)
118 """ called at the beginning of each year
119 sets Points to zero and possibly erases social links (based on parameter
'EraseNetwork')
126 """ updates values for display
128 Colour = 'green%d' % int(1 + 10 * (1 - float(self.Age)/(1+self.
Param(
'AgeMax'))))
129 if infancy
and not self.adult(): Colour =
'red'
130 if self.Features: y = self.Features[self.Features.keys()[0]]
142 """ Social benefit from having friends - called by Learning
148 return "%s[%s]" % (self.
ID, str(self.Features))
151 """ defines a population of interacting agents
153 def __init__(self, parameters, NbAgents, Observer, IndividualClass=None, features={}):
154 """ creates a population of social individuals
156 if IndividualClass
is None: IndividualClass = Social_Individual
158 self.
Pop = [IndividualClass(IdNb, maxQuality=NbAgents, features=features.keys(),
159 parameters=parameters)
for IdNb
in range(NbAgents)]
166 """ returns the list of agents' locations
168 return [(A.ID, A.location)
for A
in self.
Pop]
171 """ Returns agents of neighbouring qualitied
173 AgentQualityRank = self.Pop.index(Agent)
174 return [self.
Pop[NBhood]
for NBhood
in [AgentQualityRank - 1, AgentQualityRank + 1]
175 if NBhood >= 0
and NBhood < self.
PopSize]
178 """ average signal in the population
181 for I
in self.
Pop: Avg += I.SignalLevel
182 if self.
Pop: Avg /= len(self.
Pop)
186 """ average value of Feature's value
189 for I
in self.
Pop: Avg += I.feature(Feature)
190 if self.
Pop: Avg /= len(self.
Pop)
194 """ average distance between friends
199 if BF: FD.append(abs(I.Quality - BF.Quality))
200 if FD:
return sum(FD) / len(FD)
204 """ Updates agents positions and social links for display.
205 Updates average feature values for curves
207 if self.
Obs.Visible():
208 for agent
in self.
Pop:
209 agent.update(infancy=self.
Obs.hot_phase())
212 self.
Obs.Alliances = [(agent.ID, [T.ID
for T
in agent.social_signature()])
for agent
in self.
Pop]
216 Colours = [
'brown',
'blue',
'red',
'green',
'white']
217 for F
in sorted(list(self.
Features.keys())):
219 Legend=
'Avg of %s' % F)
222 """ tells agents to reinitialize each year
224 for agent
in self.
Pop: agent.reinit()
227 """ interactions occur within a group
229 if NbInteractions
is None: NbInteractions = self.
Param(
'NbInteractions')
230 if group
is None: group = self.
Pop
231 for encounter
in range(NbInteractions):
232 Player, Partner = sample(group, 2)
233 Player.Interact(Partner)
236 """ called at each 'run', several times per year
238 Learners = sample(self.Pop, Tools.chances(self.Param('LearningProbability')/100.0, len(self.
Pop)))
240 for agent
in self.
Pop:
242 if agent
in Learners:
243 agent.Learns(self.
neighbours(agent), hot=self.
Obs.hot_phase())
245 for agent
in self.
Pop:
246 agent.wins(agent.Points)
249 """ This procedure is repeatedly called by the simulation thread.
250 It increments the year through season().
251 Then for each run (there are NbRunPerYear runs each year),
252 interactions take place within groups
261 for Run
in range(self.
Param(
'NbRunPerYear')):
270 for groupID
in range(self.
NbGroup):
271 group = Pop[groupID * GroupLength: (groupID + 1) * GroupLength]
283def Start(Params=None, PopClass=Social_Population, ObsClass=Social_Observer, DumpFeatures=None, Windows='FNC'):
284 """ Launches the simulation
286 if Params
is None: Params =
Global()
287 Observer_ = ObsClass(Params)
288 Observer_.setOutputDir(
'___Results')
290 if 'F' in Windows: Views.append((
'Field', 770, 70, 520, 370))
291 if 'N' in Windows: Views.append((
'Network', 530, 200))
293 Observer_.recordInfo(
'DefaultViews', Views)
295 Pop = PopClass(Params, Params[
'NbAgents'], Observer_)
296 if DumpFeatures
is None: DumpFeatures = list(Pop.Features.keys()) + [
'DistanceToBestFriend']
297 Observer_.recordInfo(
'DumpFeatures', DumpFeatures)
298 BatchMode = Params[
'BatchMode']
308 Evolife_Batch.Start(Pop.One_Run, Observer_)
316 Evolife_Window.Start(Pop.One_Run, Observer_, Capabilities=Windows+
'P',
317 Options={
'Background':Params.get(
'Background',
'lightblue')})
318 except Exception
as Msg:
319 from sys
import excepthook, exc_info
320 excepthook(exc_info()[0],exc_info()[1],exc_info()[2])
323 Params.Dump_(Pop.Dump, Observer_.get_info(
'ResultFile'), Observer_.get_info(
'DumpFeatures'),
324 Observer_.get_info(
'ExperienceID'), Verbose =
not BatchMode)
325 if not BatchMode: print(
"Bye.......")
331if __name__ ==
"__main__":
333 if Gbl[
'RandomSeed'] > 0: random.seed(Gbl[
'RandomSeed'])
338__author__ =
'Dessalles'
Augmented version of Friends for asymmetrical links - replaces 'Alliances'.
def forgetAll(self)
calls 'detach' for self's followers and then for self.
def forgetAll(self)
The individual quits its friends
Global elements, mainly parameters.
def __init__(self, ConfigFile='_Params.evo')
def Dump_(self, PopDump, ResultFileName, DumpFeatures, ExpeID, Verbose=False)
Saves parameter values, then agents' investment in signalling, then agents' distance to best friend.
A social individual has friends and can learn.
def Interact(self, Partner)
to be overloaded
def __init__(self, IdNb, features={}, maxQuality=100, parameters=None, SocialSymmetry=True)
Initalizes social links and learning parameters.
def assessment(self)
Social benefit from having friends - called by Learning (to be overloaded)
def reinit(self)
called at the beginning of each year sets Points to zero and possibly erases social links (based on p...
def update(self, infancy=True)
updates values for display
def Reset(self, Newborn=True)
called by Learner at initialization and when born again Resets social links and learning experience
Stores some global observation and display variables.
def __init__(self, Parameters=None)
Experiment_Observer constructor.
def get_data(self, Slot, Consumption=True)
Experiment_Observer's get_data + slot 'Network' that contains social links.
def hot_phase(self)
The hot phase is a limited amount of time, controlled by the 'LearnHorizon' parameter,...
defines a population of interacting agents
def FeatureAvg(self, Feature)
average value of Feature's value
def learning(self)
called at each 'run', several times per year
def __init__(self, parameters, NbAgents, Observer, IndividualClass=None, features={})
creates a population of social individuals
def interactions(self, group=None, NbInteractions=None)
interactions occur within a group
def season_initialization(self)
tells agents to reinitialize each year
def FriendDistance(self)
average distance between friends
def neighbours(self, Agent)
Returns agents of neighbouring qualitied.
def positions(self)
returns the list of agents' locations
def One_Run(self)
This procedure is repeatedly called by the simulation thread.
def SignalAvg(self)
average signal in the population
def display(self)
Updates agents positions and social links for display.
def Start(Params=None, PopClass=Social_Population, ObsClass=Social_Observer, DumpFeatures=None, Windows='FNC')
Launches the simulation.