Class: Algorithmically::Swarm::ParticleSwarm

Inherits:
Object
  • Object
show all
Defined in:
lib/Algorithmically/Swarm/particle_swarm.rb

Instance Method Summary collapse

Constructor Details

#initialize(problem_size, max_gens, search_space, vel_space, pop_size, max_vel, c1, c2) ⇒ ParticleSwarm

Returns a new instance of ParticleSwarm.



6
7
8
9
10
11
12
# File 'lib/Algorithmically/Swarm/particle_swarm.rb', line 6

def initialize(problem_size, max_gens, search_space, vel_space, pop_size, max_vel, c1, c2)
  @search_space, @vel_space = search_space, vel_space
  @search_space = Array.new(problem_size) {|i| [-5, 5]}
  @vel_space = Array.new(problem_size) {|i| [-1, 1]}
  best = search(max_gens, @search_space, @vel_space, pop_size, max_vel, c1, c2)
  puts "done! Solution: f=#{best[:cost]}, s=#{best[:position].inspect}"
end

Instance Method Details

#create_particle(search_space, vel_space) ⇒ Object



24
25
26
27
28
29
30
31
32
# File 'lib/Algorithmically/Swarm/particle_swarm.rb', line 24

def create_particle(search_space, vel_space)
  particle = {}
  particle[:position] = random_vector(search_space)
  particle[:cost] = objective_function(particle[:position])
  particle[:b_position] = Array.new(particle[:position])
  particle[:b_cost] = particle[:cost]
  particle[:velocity] = random_vector(vel_space)
  particle
end

#get_global_best(population, current_best = nil) ⇒ Object



34
35
36
37
38
39
40
41
42
43
# File 'lib/Algorithmically/Swarm/particle_swarm.rb', line 34

def get_global_best(population, current_best=nil)
  population.sort! { |x, y| x[:cost] <=> y[:cost] }
  best = population.first
  if current_best.nil? or best[:cost] <= current_best[:cost]
    current_best = {}
    current_best[:position] = Array.new(best[:position])
    current_best[:cost] = best[:cost]
  end
  current_best
end

#objective_function(vector) ⇒ Object



14
15
16
# File 'lib/Algorithmically/Swarm/particle_swarm.rb', line 14

def objective_function(vector)
  vector.inject(0.0) { |sum, x| sum + (x ** 2.0) }
end

#random_vector(minmax) ⇒ Object



18
19
20
21
22
# File 'lib/Algorithmically/Swarm/particle_swarm.rb', line 18

def random_vector(minmax)
  Array.new(minmax.size) do |i|
    minmax[i][0] + ((minmax[i][1] - minmax[i][0]) * rand())
  end
end

#search(max_gens, search_space, vel_space, pop_size, max_vel, c1, c2) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/Algorithmically/Swarm/particle_swarm.rb', line 74

def search(max_gens, search_space, vel_space, pop_size, max_vel, c1, c2)
  pop = Array.new(pop_size) { create_particle(search_space, vel_space) }
  gbest = get_global_best(pop)
  max_gens.times do |gen|
    pop.each do |particle|
      update_velocity(particle, gbest, max_vel, c1, c2)
      update_position(particle, search_space)
      particle[:cost] = objective_function(particle[:position])
      update_best_position(particle)
    end
    gbest = get_global_best(pop, gbest)
    puts " > gen #{gen+1}, fitness=#{gbest[:cost]}"
  end
  gbest
end

#update_best_position(particle) ⇒ Object



68
69
70
71
72
# File 'lib/Algorithmically/Swarm/particle_swarm.rb', line 68

def update_best_position(particle)
  return if particle[:cost] > particle[:b_cost]
  particle[:b_cost] = particle[:cost]
  particle[:b_position] = Array.new(particle[:position])
end

#update_position(part, bounds) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/Algorithmically/Swarm/particle_swarm.rb', line 55

def update_position(part, bounds)
  part[:position].each_with_index do |v, i|
    part[:position][i] = v + part[:velocity][i]
    if part[:position][i] > bounds[i][1]
      part[:position][i]=bounds[i][1]-(part[:position][i]-bounds[i][1]).abs
      part[:velocity][i] *= -1.0
    elsif part[:position][i] < bounds[i][0]
      part[:position][i]=bounds[i][0]+(part[:position][i]-bounds[i][0]).abs
      part[:velocity][i] *= -1.0
    end
  end
end

#update_velocity(particle, gbest, max_v, c1, c2) ⇒ Object



45
46
47
48
49
50
51
52
53
# File 'lib/Algorithmically/Swarm/particle_swarm.rb', line 45

def update_velocity(particle, gbest, max_v, c1, c2)
  particle[:velocity].each_with_index do |v, i|
    v1 = c1 * rand() * (particle[:b_position][i] - particle[:position][i])
    v2 = c2 * rand() * (gbest[:position][i] - particle[:position][i])
    particle[:velocity][i] = v + v1 + v2
    particle[:velocity][i] = max_v if particle[:velocity][i] > max_v
    particle[:velocity][i] = -max_v if particle[:velocity][i] < -max_v
  end
end