Class: DynamicalSystem

Inherits:
Object
  • Object
show all
Defined in:
lib/dynamical_system.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rule, initial_state) ⇒ DynamicalSystem

Returns a new instance of DynamicalSystem.



25
26
27
28
29
30
31
32
33
34
# File 'lib/dynamical_system.rb', line 25

def initialize(rule, initial_state)
  if DynamicalSystem.is_valid_rule?(rule)
    @rule = rule
    @states = rule.keys
    @state = initial_state
    @history = [initial_state]
  else
    raise RuleError
  end
end

Instance Attribute Details

#historyObject (readonly)

Returns the value of attribute history.



4
5
6
# File 'lib/dynamical_system.rb', line 4

def history
  @history
end

#stateObject

Returns the value of attribute state.



4
5
6
# File 'lib/dynamical_system.rb', line 4

def state
  @state
end

#statesObject (readonly)

Returns the value of attribute states.



4
5
6
# File 'lib/dynamical_system.rb', line 4

def states
  @states
end

Class Method Details

.is_valid_rule?(rule) ⇒ Boolean

Returns:

  • (Boolean)


6
7
8
9
# File 'lib/dynamical_system.rb', line 6

def self.is_valid_rule?(rule)
  return (rule.is_a?(Hash) &&
          rule.values.to_set.subset?(rule.keys.to_set)) ? true : false
end

.random(number_of_states) ⇒ Object



11
12
13
14
15
16
17
18
# File 'lib/dynamical_system.rb', line 11

def self.random(number_of_states)
  rule = {}
  (1..number_of_states).each do |s|
    r = rand(number_of_states) + 1
    rule.merge!({ "s#{s}".to_sym => "s#{r}".to_sym })
  end
  return self.new(rule, :s1)
end

Instance Method Details

#backward_orbit(state = @state) ⇒ Object

Raises:



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/dynamical_system.rb', line 76

def backward_orbit(state = @state)
  raise RuleError, "Is not bijective" unless is_bijective?
  backward_orbit = [state]
  old_state = @rule.key(state)
  until backward_orbit.include?(old_state) do
    backward_orbit << old_state
    old_state = @rule.key(old_state)
  end
  backward_orbit << old_state #needed to see the cycle
  return backward_orbit
end

#cycle_from_forward_orbit(forward_orbit) ⇒ Object



93
94
95
# File 'lib/dynamical_system.rb', line 93

def cycle_from_forward_orbit(forward_orbit)
  return forward_orbit[forward_orbit.index(forward_orbit.last)...-1]
end

#cyclesObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/dynamical_system.rb', line 97

def cycles
  return @cycles if @cycles
  @cycles = []
  visited_states = []
  states_array = Array(@states)
  until visited_states.size == @states.size do
    start_state = (states_array - visited_states).sample
    forward_orbit = forward_orbit(start_state)
    cycle = cycle_from_forward_orbit(forward_orbit)
    cycle_set = cycle.to_set
    cycle_sets = @cycles.map { |c| c.to_set }
    @cycles << cycle unless cycle_sets.include?(cycle_set)
    visited_states |= forward_orbit
  end
  return @cycles
end

#evolve(steps = 1, state = @state) ⇒ Object



47
48
49
50
# File 'lib/dynamical_system.rb', line 47

def evolve(steps = 1, state = @state)
  steps.times { state = @rule[state] }
  return state
end

#evolve!(steps = 1, state = @state) ⇒ Object



41
42
43
44
45
# File 'lib/dynamical_system.rb', line 41

def evolve!(steps = 1, state = @state)
  set_state(state) if state != @state
  steps.times { @state = @rule[@state]; @history << @state }
  return @state
end

#fixed_pointsObject



118
119
120
# File 'lib/dynamical_system.rb', line 118

def fixed_points
  @fixed_points ||= @states.select { |s| is_fixed_point?(s) }
end

#forward_orbit(state = @state) ⇒ Object



65
66
67
68
69
70
71
72
73
74
# File 'lib/dynamical_system.rb', line 65

def forward_orbit(state = @state)
  forward_orbit = [state]
  new_state = @rule[state]
  until forward_orbit.include?(new_state) do
    forward_orbit << new_state
    new_state = @rule[new_state]
  end
  forward_orbit << new_state #needed to see the cycle
  return forward_orbit
end

#inspectObject



20
21
22
23
# File 'lib/dynamical_system.rb', line 20

def inspect
  puts "state : #{@state}\n" + "history : #{history}\n" +
       "rule : #{@rule}\n" + "states : #{@states}"
end

#is_bijective?Boolean

Returns:

  • (Boolean)


127
128
129
# File 'lib/dynamical_system.rb', line 127

def is_bijective?
  return @states.size == @rule.values.uniq.size
end

#is_fixed_point?(state = @state) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
# File 'lib/dynamical_system.rb', line 114

def is_fixed_point?(state = @state)
  return state == evolve(1, state) ? true : false
end

#is_invariant_set?(state_array) ⇒ Boolean

Returns:

  • (Boolean)


122
123
124
125
# File 'lib/dynamical_system.rb', line 122

def is_invariant_set?(state_array)
  new_state_array = state_array.map { |s| evolve(1, s) }
  return new_state_array.to_set == state_array.to_set ? true : false
end

#orbit(state = @state) ⇒ Object

Raises:



88
89
90
91
# File 'lib/dynamical_system.rb', line 88

def orbit(state = @state)
  raise RuleError, "Is not bijective" unless is_bijective?
  return backward_orbit(state)[0...-1] += (forward_orbit(state))
end

#path(steps = 1, state = @state) ⇒ Object



59
60
61
62
63
# File 'lib/dynamical_system.rb', line 59

def path(steps = 1, state = @state)
  path = [state]
  steps.times { state = @rule[state]; path << state }
  return path
end

#path!(steps = 1, state = @state) ⇒ Object



52
53
54
55
56
57
# File 'lib/dynamical_system.rb', line 52

def path!(steps = 1, state = @state)
  set_state(state) if state != @state
  path = [@state]
  steps.times { @state = @rule[@state]; @history << @state; path << @state }
  return path
end