Class: Stamina::TransitionSystem::Equivalence

Inherits:
Object
  • Object
show all
Defined in:
lib/stamina-core/stamina/transition_system/equivalence.rb

Direct Known Subclasses

Automaton::Equivalence

Defined Under Namespace

Classes: EquivThroughDeco

Instance Method Summary collapse

Instance Method Details

#call(ts1, ts2, &explain) ⇒ Object

Executes the equivalence algorithm on two transition systems ‘ts1` and `ts2`. Returns true if they are considered equivalent, false otherwise.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/stamina-core/stamina/transition_system/equivalence.rb', line 86

def call(ts1, ts2, &explain)
  @explain = explain
  catch(:fail) do
    equivalent_systems!(ts1, ts2)
    i1, i2 = ts1.initial_state, ts2.initial_state
    fail "No initial state on ts1" unless i1
    fail "No initial state on ts2" unless i2
    equivalent_states!(i1, i2)
    mapping = {}
    EquivThroughDeco.new(ts2, self).call(ts1, mapping)
    return !mapping.any?{|k,v| v.nil?}
  end
  return false
ensure
  @explain = nil
end

#equivalent_edges!(s, t) ⇒ Object



32
33
34
35
# File 'lib/stamina-core/stamina/transition_system/equivalence.rb', line 32

def equivalent_edges!(s, t)
  fail "Non equivalent edges `#{s}` and `#{t}`" unless equivalent_edges?(s,t)
  true
end

#equivalent_edges?(e, f) ⇒ Boolean

Returns true if ‘e` and `f` must be considered equivalent, false otherwise.

Returns:

  • (Boolean)


28
29
30
# File 'lib/stamina-core/stamina/transition_system/equivalence.rb', line 28

def equivalent_edges?(e, f)
  e.raw_data == f.raw_data
end

#equivalent_states!(s, t) ⇒ Object



22
23
24
25
# File 'lib/stamina-core/stamina/transition_system/equivalence.rb', line 22

def equivalent_states!(s, t)
  fail "Non equivalent states `#{s}` and `#{t}`" unless equivalent_states?(s,t)
  true
end

#equivalent_states?(s, t) ⇒ Boolean

Returns true if ‘s` and `t` must be considered equivalent, false otherwise.

Returns:

  • (Boolean)


18
19
20
# File 'lib/stamina-core/stamina/transition_system/equivalence.rb', line 18

def equivalent_states?(s, t)
  s.raw_data == t.raw_data
end

#equivalent_systems!(s, t) ⇒ Object



12
13
14
15
# File 'lib/stamina-core/stamina/transition_system/equivalence.rb', line 12

def equivalent_systems!(s, t)
  fail "Non equivalent systems `#{s}` and `#{t}`" unless equivalent_systems?(s,t)
  true
end

#equivalent_systems?(s, t) ⇒ Boolean

Returns true if ‘s` and `t` must be considered equivalent, false otherwise.

Returns:

  • (Boolean)


6
7
8
9
10
# File 'lib/stamina-core/stamina/transition_system/equivalence.rb', line 6

def equivalent_systems?(s, t)
  (s.state_count == t.state_count) &&
  (s.edge_count  == t.edge_count)  &&
  (s.raw_data    == t.raw_data)
end

#fail(message) ⇒ Object



103
104
105
106
# File 'lib/stamina-core/stamina/transition_system/equivalence.rb', line 103

def fail(message)
  @explain.call(message) if @explain
  throw :fail
end

#find_edge_counterpart(reference_state, operand_edge) ⇒ Object

Finds the edge counterpart of ‘operand_edge` as an outgoing edge of `reference_state`. The default implementation takes an edge that shares the same symbol as operand_edge.



40
41
42
43
# File 'lib/stamina-core/stamina/transition_system/equivalence.rb', line 40

def find_edge_counterpart(reference_state, operand_edge)
  symbol = operand_edge.symbol
  reference_state.out_edges.find{|e| e.symbol==symbol}
end