Class: Legion::Extensions::Agentic::Homeostasis::Pendulum::Helpers::Pendulum

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pole_pair:, amplitude: 0.5, period: 10.0, damping: Constants::DAMPING_RATE) ⇒ Pendulum

Returns a new instance of Pendulum.

Raises:

  • (ArgumentError)


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 12

def initialize(pole_pair:, amplitude: 0.5, period: 10.0, damping: Constants::DAMPING_RATE)
  raise ArgumentError, "unknown pole_pair: #{pole_pair}" unless Constants.valid_pole_pair?(pole_pair)
  raise ArgumentError, 'amplitude must be 0.0..1.0' unless amplitude.between?(0.0, 1.0)
  raise ArgumentError, 'period must be positive' unless period.positive?
  raise ArgumentError, 'damping must be >= 0' unless damping >= 0.0

  @id               = SecureRandom.uuid
  @pole_pair        = pole_pair
  @amplitude        = amplitude.clamp(0.0, 1.0)
  @period           = period.to_f
  @damping          = damping.to_f
  @current_position = 0.0
  @created_at       = Time.now.utc
  @swings           = 0
end

Instance Attribute Details

#amplitudeObject (readonly)

Returns the value of attribute amplitude.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 10

def amplitude
  @amplitude
end

#created_atObject (readonly)

Returns the value of attribute created_at.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 10

def created_at
  @created_at
end

#current_positionObject (readonly)

Returns the value of attribute current_position.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 10

def current_position
  @current_position
end

#dampingObject (readonly)

Returns the value of attribute damping.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 10

def damping
  @damping
end

#idObject (readonly)

Returns the value of attribute id.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 10

def id
  @id
end

#periodObject (readonly)

Returns the value of attribute period.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 10

def period
  @period
end

#pole_pairObject (readonly)

Returns the value of attribute pole_pair.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 10

def pole_pair
  @pole_pair
end

#swingsObject (readonly)

Returns the value of attribute swings.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 10

def swings
  @swings
end

Instance Method Details

#amplitude_labelObject



56
57
58
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 56

def amplitude_label
  Constants.amplitude_label(@amplitude)
end

#at_pole_a?Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 48

def at_pole_a?
  @current_position <= -0.5
end

#at_pole_b?Boolean

Returns:

  • (Boolean)


52
53
54
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 52

def at_pole_b?
  @current_position >= 0.5
end

#damp!Object



35
36
37
38
39
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 35

def damp!
  @amplitude = (@amplitude * (1.0 - @damping)).round(10).clamp(0.0, 1.0)
  @current_position = (@current_position * (1.0 - @damping)).round(10).clamp(-1.0, 1.0)
  @amplitude
end

#dominant_poleObject



68
69
70
71
72
73
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 68

def dominant_pole
  poles = Constants::POLE_PAIRS.fetch(@pole_pair)
  return :neutral if @current_position.abs < 0.1

  @current_position.negative? ? poles[0] : poles[1]
end

#position_at(time) ⇒ Object



41
42
43
44
45
46
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 41

def position_at(time)
  elapsed = time.to_f
  angular_frequency = (2.0 * Math::PI) / @period
  decay = Math.exp(-@damping * elapsed)
  (@amplitude * decay * Math.cos(angular_frequency * elapsed)).round(10).clamp(-1.0, 1.0)
end

#resonant_with?(frequency) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
63
64
65
66
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 60

def resonant_with?(frequency)
  return false unless frequency.positive?

  natural_frequency = 1.0 / @period
  ratio = frequency / natural_frequency
  (ratio - 1.0).abs <= 0.05
end

#swing!(force: 0.0) ⇒ Object



28
29
30
31
32
33
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 28

def swing!(force: 0.0)
  force_clamped = force.to_f.clamp(-1.0, 1.0)
  @current_position = (@current_position + force_clamped).clamp(-1.0, 1.0)
  @swings += 1
  @current_position
end

#to_hObject



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/legion/extensions/agentic/homeostasis/pendulum/helpers/pendulum.rb', line 75

def to_h
  poles = Constants::POLE_PAIRS.fetch(@pole_pair)
  {
    id:               @id,
    pole_pair:        @pole_pair,
    pole_a:           poles[0],
    pole_b:           poles[1],
    amplitude:        @amplitude.round(10),
    amplitude_label:  amplitude_label,
    period:           @period,
    damping:          @damping,
    current_position: @current_position.round(10),
    dominant_pole:    dominant_pole,
    at_pole_a:        at_pole_a?,
    at_pole_b:        at_pole_b?,
    swings:           @swings,
    created_at:       @created_at
  }
end