1
2 """
3 Helper functions for fitting.
4 """
5 __all__ = ['populate']
6 import numpy
7
8 -def populate(size, pars, radius=100, elitism=True):
9 """
10 Generate a population within a parameter space.
11
12 The population will be centered on the initial value, with the
13 given radius. Radius is a percentage of the total space, or a
14 percentage of the initial value if the space is unbounded.
15 If radius is given as a vector, the radius is the length of the
16 selection box in each dimension of the problem space. This is
17 clipped to the bounds of the problem.
18
19 Note that the term radius is a bit misleading since the volume
20 used is rectilinear rather than ellipsoidal, but it captures the
21 notion of whether values should be clustered tightly in the
22 available search space, or ranged broadly.
23 """
24
25 x0 = numpy.array([p.value for p in pars])
26 bounds = numpy.array([p.range for p in pars]).T
27 lo,hi = bounds
28
29
30
31
32 if numpy.isscalar(radius):
33 step = radius*0.01*(hi-lo)
34 idx = numpy.isinf(step)
35 step[idx] = abs(x0[idx])*radius*0.01
36 step[step==0] = 1
37 else:
38 step = radius
39 if numpy.isinf(step).any():
40 raise ValueError('individual radii must be finite')
41
42
43
44 boxlo,boxhi = x0-step,x0+step
45 boxlo = boxlo.clip(lo, max(boxlo))
46 boxhi = boxhi.clip(min(boxhi), hi)
47 delta = boxhi-boxlo
48
49
50
51 P = numpy.random.rand(size,len(pars))*delta+boxlo
52 if elitism:
53 P[0] = x0
54
55 return P
56
62 def __repr__(self):
63 return "P(%s in [%s, %s])"%(self.value, self.range[0], self.range[1])
64
65 pop = populate(10, [P(1,[0,3]),P(2,[0,3]),P(3,[2,4])])
66
67 assert (2 <= pop[:,2]).all() and (pop[:,2] <= 4).all()
68 assert pop.shape[0] == 10 and pop.shape[1] == 3
69 assert pop[0,2] == 3
70
71 pop = populate(10, [P(2,[-inf, 3]), P(5,[3,inf]),
72 P(2,[-inf, inf]), P(-2,[-inf,inf]),
73 P(0,[-inf,inf])])
74
75 assert (0 <= pop[:,0]).all() and (pop[:,0] <= 3).all()
76 assert (3 <= pop[:,1]).all() and (pop[:,1] <= 10).all()
77 assert (0 <= pop[:,2]).all() and (pop[:,2] <= 4).all()
78 assert (-4 <= pop[:,3]).all() and (pop[:,3] <= 0).all()
79 assert (-1 <= pop[:,4]).all() and (pop[:,4] <= 1).all()
80
81
82 if __name__ == "__main__": test()
83