-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathswarm.go
113 lines (99 loc) · 2.66 KB
/
swarm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package evoli
import "sync"
var (
// ErrLearningCoef - c1 & c2 must be > 0
ErrLearningCoef = "ErrLearningCoef - c1 & c2 must be > 0"
)
type swarm struct {
evolution
bests map[Individual]Individual
positioner Positioner
c1, c2 float64
}
// NewSwarm - constructor for particles swarm optimization algorithm
// typical value for learning coef is c1 = c2 = 2
// the bigger are the coefficients the faster the population converge
func NewSwarm(pop Population, positioner Positioner, c1, c2 float64, evaluater Evaluater) Evolution {
if c1 <= 0 || c2 <= 0 {
panic(ErrLearningCoef)
}
return &swarm{newEvolution(pop, evaluater), make(map[Individual]Individual), positioner, c1, c2}
}
func (s *swarm) Next() error {
newPop, err := s.evaluation(s.pop)
if err != nil {
return err
}
newPop, err = s.positioning(newPop)
if err != nil {
return err
}
s.pop = newPop
return nil
}
func (s *swarm) evaluation(pop Population) (Population, error) {
length := pop.Len()
for i := 0; i < length; i++ {
individual := pop.Get(i)
fitness, err := s.evaluater.Evaluate(individual)
if err != nil {
return pop, err
}
best, exists := s.bests[individual]
if !exists || fitness > best.Fitness() {
s.bests[individual] = individual
}
individual.SetFitness(fitness)
}
return pop, nil
}
func (s *swarm) positioning(pop Population) (Population, error) {
newPop := NewPopulation(pop.Cap())
gBest := pop.Max()
individuals := pop.Slice()
for _, indiv := range individuals {
pBest := s.bests[indiv]
newIndiv, err := s.positioner.Position(indiv, pBest, gBest, s.c1, s.c2)
if err != nil {
return nil, err
}
delete(s.bests, indiv)
s.bests[newIndiv] = pBest
newPop.Add(newIndiv)
}
return newPop, nil
}
func (s *swarm) SetPopulation(pop Population) {
s.bests = make(map[Individual]Individual)
s.evolution.SetPopulation(pop)
}
type swarmSync struct {
swarm
sync.RWMutex
}
// NewSwarmSync - constructor for particles swarm optimization algorithm (sync impl)
// typical value for learning coef is c1 = c2 = 2
// the bigger are the coefficients the faster the population converge
func NewSwarmSync(pop Population, positioner Positioner, c1, c2 float64, evaluater Evaluater) Evolution {
return &swarmSync{*NewSwarm(pop, positioner, c1, c2, evaluater).(*swarm), sync.RWMutex{}}
}
func (s *swarmSync) Next() error {
s.Lock()
defer s.Unlock()
return s.swarm.Next()
}
func (s *swarmSync) Population() Population {
s.RLock()
defer s.RUnlock()
return s.swarm.Population()
}
func (s *swarmSync) SetPopulation(pop Population) {
s.Lock()
defer s.Unlock()
s.swarm.SetPopulation(pop)
}
func (s *swarmSync) Alpha() Individual {
s.RLock()
defer s.RUnlock()
return s.swarm.Alpha()
}