-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpso.go
114 lines (101 loc) · 2.42 KB
/
pso.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
114
package eago
import (
"fmt"
"math/rand"
"time"
)
type PSO struct {
NParticle int
NStep int
NDim int
Min float64
Max float64
Coefficients []float64
objectiveFunc func([]float64) float64
GlobalBest float64
GlobalBestPos []float64
swarm swarm
PrintCallBack func()
}
type particle struct {
position []float64
velocity []float64
fitness float64
personalBest float64
personalBestPos []float64
}
type swarm []*particle
func NewDefaultPSO() *PSO {
return &PSO{
Coefficients: []float64{0.8, 0.8, 0.8},
}
}
func(pso *PSO) initSwarm() {
var min float64
pos := make([]float64, pso.NDim)
swarm := make(swarm, pso.NParticle)
for i := range swarm {
swarm[i] = pso.initParticle()
if i == 0 {
min = swarm[i].fitness
pos = swarm[i].position
} else {
if swarm[i].fitness < min {
min = swarm[i].fitness
pos = swarm[i].position
}
}
}
pso.swarm = swarm
pso.GlobalBestPos = append([]float64{}, pos...)
pso.GlobalBest = min
}
func(pso *PSO) initParticle() *particle {
rand.Seed(time.Now().UnixNano())
pos := InitFloatVector(pso.NDim, pso.Max, pso.Min)
fitness := pso.objectiveFunc(pos)
return &particle{
position: pos,
velocity: []float64{rand.Float64(), rand.Float64()},
fitness: fitness,
personalBest: fitness,
personalBestPos: pos,
}
}
func(pso *PSO) move() {
rand.Seed(time.Now().UnixNano())
r1 := rand.Float64()
r2 := rand.Float64()
c := pso.Coefficients
for _, p := range pso.swarm {
for i := range p.position {
p.velocity[i] = c[0]*p.velocity[i] + c[1]*(pso.GlobalBestPos[i]-p.position[i])*r1 + c[2]*(p.personalBestPos[i]-p.position[i])*r2
p.position[i] += p.velocity[i]
}
p.fitness = pso.objectiveFunc(p.position)
// Update personal best
if p.fitness < p.personalBest {
p.personalBest = p.fitness
p.personalBestPos = append([]float64{}, p.position...)
}
// Update global best
if p.fitness < pso.GlobalBest {
pso.GlobalBest = p.fitness
pso.GlobalBestPos = append([]float64{}, p.position...)
}
}
}
func (pso *PSO) Minimize(f func([]float64) float64, nDim int) error {
pso.objectiveFunc = f
pso.NDim = nDim
pso.initSwarm()
for i := 0; i < pso.NStep; i++ {
if pso.PrintCallBack != nil {
pso.PrintCallBack()
} else {
fmt.Printf("Step %3d: Fitness=%.3f Position=%.3f\n", i, pso.GlobalBest, pso.GlobalBestPos)
}
pso.move()
}
return nil
}