Algorithmically 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/lib/Algorithmically.rb +2 -0
- data/lib/Algorithmically/Swarm/particle_swarm.rb +93 -0
- data/lib/Algorithmically/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c3ff69c1deb1ef40a3b013235db5301c5fabe69
|
4
|
+
data.tar.gz: 079f3e9fa0f0855bbdff52e73d6047e5a1c8e56d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39a4454297e4961ba194fecad4c33c03447b00e702e5411251ccc43dd966fee3d0159af90ad6b9f3887a19788b702427d9239f8ba44b615be9b2e96f35f3cdd1
|
7
|
+
data.tar.gz: 3bf6a86a8e384a28438e38ab15cf3d00626fcd38c3cc7b91326b079ee6bb3812eee3f741cffa8e0b3b694f16c97ec0923ed58a1fb046640e59eae3c034a30195
|
data/README.md
CHANGED
data/lib/Algorithmically.rb
CHANGED
@@ -4,10 +4,12 @@ require 'Algorithmically/Neural/perceptron'
|
|
4
4
|
require 'Algorithmically/Stochastic/random_search'
|
5
5
|
require 'Algorithmically/Stochastic/hill_climbing'
|
6
6
|
require 'Algorithmically/Stochastic/guided_local_search'
|
7
|
+
require 'Algorithmically/Swarm/particle_swarm'
|
7
8
|
|
8
9
|
|
9
10
|
module Algorithmically
|
10
11
|
include Evolutionary
|
11
12
|
include Neural
|
12
13
|
include Stochastic
|
14
|
+
include Swarm
|
13
15
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Algorithmically
|
2
|
+
module Swarm
|
3
|
+
|
4
|
+
class ParticleSwarm
|
5
|
+
|
6
|
+
def initialize(problem_size, max_gens, search_space, vel_space, pop_size, max_vel, c1, c2)
|
7
|
+
@search_space, @vel_space = search_space, vel_space
|
8
|
+
@search_space = Array.new(problem_size) {|i| [-5, 5]}
|
9
|
+
@vel_space = Array.new(problem_size) {|i| [-1, 1]}
|
10
|
+
best = search(max_gens, @search_space, @vel_space, pop_size, max_vel, c1, c2)
|
11
|
+
puts "done! Solution: f=#{best[:cost]}, s=#{best[:position].inspect}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def objective_function(vector)
|
15
|
+
vector.inject(0.0) { |sum, x| sum + (x ** 2.0) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def random_vector(minmax)
|
19
|
+
Array.new(minmax.size) do |i|
|
20
|
+
minmax[i][0] + ((minmax[i][1] - minmax[i][0]) * rand())
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_particle(search_space, vel_space)
|
25
|
+
particle = {}
|
26
|
+
particle[:position] = random_vector(search_space)
|
27
|
+
particle[:cost] = objective_function(particle[:position])
|
28
|
+
particle[:b_position] = Array.new(particle[:position])
|
29
|
+
particle[:b_cost] = particle[:cost]
|
30
|
+
particle[:velocity] = random_vector(vel_space)
|
31
|
+
particle
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_global_best(population, current_best=nil)
|
35
|
+
population.sort! { |x, y| x[:cost] <=> y[:cost] }
|
36
|
+
best = population.first
|
37
|
+
if current_best.nil? or best[:cost] <= current_best[:cost]
|
38
|
+
current_best = {}
|
39
|
+
current_best[:position] = Array.new(best[:position])
|
40
|
+
current_best[:cost] = best[:cost]
|
41
|
+
end
|
42
|
+
current_best
|
43
|
+
end
|
44
|
+
|
45
|
+
def update_velocity(particle, gbest, max_v, c1, c2)
|
46
|
+
particle[:velocity].each_with_index do |v, i|
|
47
|
+
v1 = c1 * rand() * (particle[:b_position][i] - particle[:position][i])
|
48
|
+
v2 = c2 * rand() * (gbest[:position][i] - particle[:position][i])
|
49
|
+
particle[:velocity][i] = v + v1 + v2
|
50
|
+
particle[:velocity][i] = max_v if particle[:velocity][i] > max_v
|
51
|
+
particle[:velocity][i] = -max_v if particle[:velocity][i] < -max_v
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def update_position(part, bounds)
|
56
|
+
part[:position].each_with_index do |v, i|
|
57
|
+
part[:position][i] = v + part[:velocity][i]
|
58
|
+
if part[:position][i] > bounds[i][1]
|
59
|
+
part[:position][i]=bounds[i][1]-(part[:position][i]-bounds[i][1]).abs
|
60
|
+
part[:velocity][i] *= -1.0
|
61
|
+
elsif part[:position][i] < bounds[i][0]
|
62
|
+
part[:position][i]=bounds[i][0]+(part[:position][i]-bounds[i][0]).abs
|
63
|
+
part[:velocity][i] *= -1.0
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def update_best_position(particle)
|
69
|
+
return if particle[:cost] > particle[:b_cost]
|
70
|
+
particle[:b_cost] = particle[:cost]
|
71
|
+
particle[:b_position] = Array.new(particle[:position])
|
72
|
+
end
|
73
|
+
|
74
|
+
def search(max_gens, search_space, vel_space, pop_size, max_vel, c1, c2)
|
75
|
+
pop = Array.new(pop_size) { create_particle(search_space, vel_space) }
|
76
|
+
gbest = get_global_best(pop)
|
77
|
+
max_gens.times do |gen|
|
78
|
+
pop.each do |particle|
|
79
|
+
update_velocity(particle, gbest, max_vel, c1, c2)
|
80
|
+
update_position(particle, search_space)
|
81
|
+
particle[:cost] = objective_function(particle[:position])
|
82
|
+
update_best_position(particle)
|
83
|
+
end
|
84
|
+
gbest = get_global_best(pop, gbest)
|
85
|
+
puts " > gen #{gen+1}, fitness=#{gbest[:cost]}"
|
86
|
+
end
|
87
|
+
gbest
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Algorithmically
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- popac
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- lib/Algorithmically/Stochastic/guided_local_search.rb
|
83
83
|
- lib/Algorithmically/Stochastic/hill_climbing.rb
|
84
84
|
- lib/Algorithmically/Stochastic/random_search.rb
|
85
|
+
- lib/Algorithmically/Swarm/particle_swarm.rb
|
85
86
|
- lib/Algorithmically/version.rb
|
86
87
|
homepage: https://github.com/popac/Algorithmically
|
87
88
|
licenses:
|