Evolife
Evolife has been developed to study Genetic algorithms, Natural evolution and behavioural ecology.
Tools.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2""" @brief Various functions. """
3
4#============================================================================#
5# EVOLIFE http://evolife.telecom-paris.fr Jean-Louis Dessalles #
6# Telecom Paris 2022-04-11 www.dessalles.fr #
7# -------------------------------------------------------------------------- #
8# License: Creative Commons BY-NC-SA #
9#============================================================================#
10# Documentation: https://evolife.telecom-paris.fr/Classes #
11#============================================================================#
12
13
14
17
18
19import sys
20import re
21import random
22import time
23from math import floor, modf, log
24
25try:
26 import EvolifeGray # gray code
27 GrayTable = EvolifeGray.GrayCode() # pre-computes a Gray code into a table for rapid acess
28except ImportError:
29 pass
30
31
32def decrease(x, M, Selection):
33 """ Computes a decreasing function of x in [0,M] which sums to 1
34 1/(x+M) normalized for x in [0,M]
35 """
36
37 def one_value(x):
38 # if x >= 0: return 1.0/(x+(1.0*M)/Selection) / log(1+Selection/float(M))
39 if x >= 0: return 1.0/(x+(1.0*M)/Selection) / log(1+Selection) # correct
40 else: error('Tools: decrease called with negative value')
41
42 global decreaseTable # memorizing values
43 try: D = decreaseTable.get((x, M, Selection), None)
44 except NameError:
45 D = None
46 decreaseTable = dict()
47 if D is not None: return D # returning memorized value
48 if M:
49 if Selection: D = (one_value(x) + one_value(x+1))/2
50 else: D = 1.0/M
51 else: D = 0
52 if len(decreaseTable) < 2000: # to avoid infinite storage
53 decreaseTable[(x, M, Selection)] = D
54 return D
55
56
57# def powerlaw(x, DropCoefficient):
58 # " Computes a decreasing power law "
59 # return (1+x) ** -DropCoefficient
60
61
62def chances(proba, N):
63 """ computes what one gets from a maximum of N with probability proba
64 """
65 C = N * proba
66 if random.random() < modf(C)[0]: # modf(3.14) == (0.14, 3.0) ; modf(3.14)[0] == 0.14
67 return int(C) + 1
68 return int(C)
69
70def uniform(proba, Max=1):
71 """ computes random uniform variable between 0 and Max
72 """
73 if isinstance(Max, int) and Max > 1:
74 return random.randint(0, Max) <= proba
75 else:
76 return Max * random.random() <= proba
77
78def fortune_wheel(Probabilities):
79 """ draws one one the pie shares y picking a location uniformly
80 """
81 if Probabilities == []: error('Calling Fortune Wheel with no probabilities')
82 Lottery = random.uniform(0, sum(Probabilities))
83 P = 0 # cumulative probability
84 for p in enumerate(Probabilities):
85 P += p[1]
86 if P >= Lottery: break
87 return p[0]
88
89def percent(x): return float(x) / 100
90
91def noise_mult(x, range_):
92 """ returns x affected by a multiplicative uniform noise
93 between 1-range_/100 and 1+range_/100
94 """
95 if (range_ > 100):
96 error("Tools: noise amplitude",str(range_))
97 return x * (1.0 + percent((2 * random.random() - 1) * range_))
98
99def noise_add(x, range_):
100 """ returns x affected by an additive uniform noise
101 between -range_ and range_
102 """
103 return x + ((2 * random.random() - 1) * range_)
104
105def transpose(Matrix):
106 """ groups ith items in each list of Matrix
107 """
108
109 #This genial version is much too slow
110 #return reduce(lambda x, y: map(lambda u,v: u+v,x,y),
111 # [map(lambda x: [x],L) for L in Matrix])
112
113 # this classical version is boring
114 # if Matrix == []:
115 # return []
116 # Result = [[0] * len(Matrix) for x in range(len(Matrix[0]))]
117 # for ii in range(len(Matrix)):
118 # for jj in range(len(Matrix[ii])):
119 # Result[jj][ii] = Matrix[ii][jj]
120 # return Result
121
122 # This version makes use of zip
123 # return zip(*Matrix) # not good for python 3
124 return list(zip(*Matrix))
125
126
127def Nb2A(Nb):
128 """ converts a number into letters - Useful to list files in correct order
129 """
130 A = chr(ord('a') + Nb // 676)
131 A += chr(ord('a')+ (Nb % 676) // 26)
132 A += chr(ord('a')+ Nb % 26)
133 return A
134
135def Nb2A0(Nb):
136 """ converts a number into a padded string
137 """
138 return ("000000" + str(Nb))[-6:]
139
140
141def Polygon(x, Points=()):
142 """ computes a polygon function crossing all points in Points
143 """
144 if x < 0: return 0
145 if x > 100: return 0
146 # Points = ((0,0),) + Points + ((1,1),)
147 found = None
148 for p in Points:
149 if x < p[0]: break
150 found = p
151 # interpolating between found and p
152 if found:
153 if p[0] == found[0]: return (p[1] - found[1])/2
154 return (found[1] + (x - found[0]) * (p[1] - found[1]) / (p[0] - found[0]))
155 return 0
156
157
158def FileAnalysis(FileName, Pattern, Flag=re.M):
159 """ Analyses the content of a file and returns all matching occurrences of Pattern
160 """
161 Filin = open(FileName,"r")
162 FContent = Filin.read() + '\n'
163 Filin.close()
164 R = re.findall(Pattern,FContent,flags=Flag) # default: Multiline analysis
165 return R
166
167def List2File(L, FileName):
168 """ Saves a list of strings into a file
169 """
170 Filout = open(FileName, "w")
171 Filout.write('\n'.join(L))
172 Filout.close()
173
174class EvolifeError(Exception):
175 def __init__(self, Origine, Msg):
176 self.Origine = Origine
177 self.Message = Msg
178
179 def __str__(self):
180 return('%s: %s' % (self.Origine, self.Message))
181
182def error(ErrMsg, Explanation=''):
183 waiting = 3
184 print("\n\n******** ERROR ************")
185 print(ErrMsg)
186 if Explanation: print(Explanation)
187 print("************ ERROR ********\n")
188 # print("************ ERROR ********\n...(%d sec.)\n\n" % waiting)
189 #raw_input('Press [Return] to exit')
190 # sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
191 # time.sleep(waiting)
192 # input('[Entree]')
193 print('[Enter]')
194 sys.stdin.readline()
195 raise EvolifeError(ErrMsg, Explanation)
196
197def warning(WMsg, Explanation=''):
198 print("\n-------- WARNING -------- %s %s -------- WARNING --------\n" % (WMsg, Explanation))
199 #raw_input('Press [Return] to exit')
200
202 """ memory buffer with limited length
203 """
204
205 def __init__(self, MaxLength):
206 self.MaxLength = MaxLength
207 self.reset()
208
209 def __len__(self): return len(self.past)
210
211 def reset(self): self.past = []
212
213 def push(self, Item):
214 self.past = self.past[-self.MaxLength+1:]
215 self.past.append(Item)
216
217 def complete(self):
218 """ full experience
219 """
220 return len(self.past) >= self.MaxLength
221
222 def retrieve(self): return self.past
223
224 def last(self):
225 if self.past != []: return self.past[-1]
226 return None
227
228 def pull(self):
229 if self.past != []: return self.past.pop()
230 return None
231
232 def __iter__(self): return iter(self.past)
233
234 def __str__(self):
235 # return ' '.join(["(%s, %0.1f)" % (str(p),v) for (p,v) in self.past])
236 # return ' '.join(["%0.1f" % b[1] for b in self.past])
237 return str(self.past)
238
239
242
243def boost():
244 return ''
245 # A technical trick - look at http://psyco.sourceforge.net/
246 #(somewhat magical, but sometimes provides impressive speeding up)
247 try:
248
249 import os.path
250 if os.path.exists('/usr/local/lib/python/site-packages'):
251 import sys
252 sys.path.append('/usr/local/lib/python/site-packages/')
253 #from psyco.classes import *
254 import psyco
255 UsePsyco = True
256 psyco.full()
257 except ImportError:
258 UsePsyco = False
259
260 return "Boosting with Psyco : %s" % UsePsyco
261
262
263
264
265if __name__ == "__main__":
266 # putting Evolife into the path (supposing we are in the same directory tree)
267 import sys
268 import os
269 import os.path
270
271 for R in os.walk(os.path.abspath('.')[0:os.path.abspath('.').find('Evo')]):
272 if os.path.exists(os.path.join(R[0],'Evolife','__init__.py')):
273 sys.path.append(R[0])
274 break
275
276
278
279 from Evolife.Scenarii.Parameters import Parameters
280 P = Parameters('../Evolife.evo')
281 print(__doc__)
282 M= 10
283 S = P.Parameter('Selectivity')
284 print("selectivity = ", int(S))
285 print([ (x,decrease(x,M,S)) for x in range(M)])
286 print(sum([decrease(x,M,S) for x in range(M)]))
287
288 # for ii in range(20):
289 # print([ chances(decrease(x,M,S),7) for x in range(M)])
290 # input('[Return]')
291
292
293
294
295
296
297__author__ = 'Dessalles'
def __init__(self, Origine, Msg)
Definition: Tools.py:175
memory buffer with limited length
Definition: Tools.py:201
def __init__(self, MaxLength)
Definition: Tools.py:205
def complete(self)
full experience
Definition: Tools.py:217
def chances(proba, N)
computes what one gets from a maximum of N with probability proba
Definition: Tools.py:62
def Nb2A(Nb)
converts a number into letters - Useful to list files in correct order
Definition: Tools.py:127
def decrease(x, M, Selection)
Computes a decreasing function of x in [0,M] which sums to 1 1/(x+M) normalized for x in [0,...
Definition: Tools.py:32
def fortune_wheel(Probabilities)
draws one one the pie shares y picking a location uniformly
Definition: Tools.py:78
def warning(WMsg, Explanation='')
Definition: Tools.py:197
def noise_add(x, range_)
returns x affected by an additive uniform noise between -range_ and range_
Definition: Tools.py:99
def percent(x)
Definition: Tools.py:89
def noise_mult(x, range_)
returns x affected by a multiplicative uniform noise between 1-range_/100 and 1+range_/100
Definition: Tools.py:91
def error(ErrMsg, Explanation='')
Definition: Tools.py:182
def uniform(proba, Max=1)
computes random uniform variable between 0 and Max
Definition: Tools.py:70
def List2File(L, FileName)
Saves a list of strings into a file.
Definition: Tools.py:167
def FileAnalysis(FileName, Pattern, Flag=re.M)
Analyses the content of a file and returns all matching occurrences of Pattern.
Definition: Tools.py:158
def Nb2A0(Nb)
converts a number into a padded string
Definition: Tools.py:135
def Polygon(x, Points=())
computes a polygon function crossing all points in Points
Definition: Tools.py:141