Class: MHL::ChargedSwarm

Inherits:
GenericSwarmBehavior show all
Defined in:
lib/mhl/charged_swarm.rb

Constant Summary collapse

DEFAULT_CHARGED_TO_NEUTRAL_RATIO =

default composition is half charged, i.e., QPSO, and half neutral, i.e., traditional PSO (with inertia), swarms

1.0

Constants inherited from GenericSwarmBehavior

GenericSwarmBehavior::DEFAULT_ALPHA, GenericSwarmBehavior::DEFAULT_C1, GenericSwarmBehavior::DEFAULT_C2, GenericSwarmBehavior::DEFAULT_CHI, GenericSwarmBehavior::PHI

Instance Method Summary collapse

Methods inherited from GenericSwarmBehavior

#update_attractor

Constructor Details

#initialize(size:, initial_positions:, initial_velocities:, charged_to_neutral_ratio: nil, alpha: nil, c1: nil, c2: nil, chi: nil, constraints: nil, logger: nil) ⇒ ChargedSwarm

Returns a new instance of ChargedSwarm.



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
# File 'lib/mhl/charged_swarm.rb', line 11

def initialize(size:, initial_positions:, initial_velocities:,
               charged_to_neutral_ratio: nil, alpha: nil, c1: nil, c2: nil,
               chi: nil, constraints: nil, logger: nil)
  @size = size

  # retrieve ratio between charged (QPSO) and neutral (constrained PSO) particles
  ratio = (charged_to_neutral_ratio || DEFAULT_CHARGED_TO_NEUTRAL_RATIO).to_f
  unless ratio > 0.0
    raise ArgumentError, 'Parameter :charged_to_neutral_ratio should be a real greater than zero!'
  end

  num_charged_particles = (@size * ratio).round
  @num_neutral_particles = @size - num_charged_particles

  # the particles are ordered, with neutral (PSO w/ inertia) particles
  # first and charged (QPSO) particles later
  @particles = Array.new(@size) do |index|
    if index < @num_neutral_particles
      Particle.new(initial_positions[index], initial_velocities[index])
    else
      QuantumParticle.new(initial_positions[index])
    end
  end

  # find problem dimension
  @dimension  = initial_positions[0].size

  @iteration = 1

  # define procedure to get dynamic value for alpha
  @get_alpha = if alpha and alpha.respond_to? :call
    alpha
  else
    ->(it) { (alpha || DEFAULT_ALPHA).to_f }
  end

  # get values for parameters C1 and C2
  @c1 = (c1 || DEFAULT_C1).to_f
  @c2 = (c2 || DEFAULT_C2).to_f

  # define procedure to get dynamic value for chi
  @get_chi = if chi and chi.respond_to? :call
    chi
  else
    ->(it) { (chi || DEFAULT_CHI).to_f }
  end

  @constraints = constraints
  @logger = logger

  if @constraints and @logger
    @logger.info "ChargedSwarm called w/ constraints: #{@constraints}"
  end
end

Instance Method Details

#mutateObject



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
# File 'lib/mhl/charged_swarm.rb', line 66

def mutate
  # get alpha parameter
  alpha = @get_alpha.call(@iteration)

  # get chi parameter
  chi = @get_chi.call(@iteration)

  # this calculates the C_n parameter (the centroid of the set of all the
  # particle attractors) as defined in equations 4.81 and 4.82 of [SUN11].
  #
  # Note: we consider ALL the particles here, not just the charged (QPSO)
  # ones. As a result, the neutral particles influence the behavior of the
  # charged ones not only by defining the swarm attractor, but also the
  # centroid.
  attractors = @particles.map {|p| p.attractor[:position] }
  c_n = 0.upto(@dimension-1).map do |j|
    attractors.inject(0.0) {|s,attr| s += attr[j] } / @size.to_f
  end

  @particles.each_with_index do |p,i|
    # remember: the particles are kept in a PSO-first and QPSO-last order
    if i < @num_neutral_particles
      p.move(chi, @c1, @c2, @swarm_attractor)
    else
      p.move(alpha, c_n, @swarm_attractor)
    end
    if @constraints
      p.remain_within(@constraints)
    end
  end

  @iteration += 1
end