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