-
Notifications
You must be signed in to change notification settings - Fork 1
/
metrics.rb
71 lines (65 loc) · 2.03 KB
/
metrics.rb
1
2
3
4
5
6
7
8
9
10
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
65
66
67
68
69
70
71
module Stamina
class Automaton
#
# Provides useful metric methods on automata.
#
# This module is automatically included by Automaton and is not intended
# to be used directly.
#
module Metrics
#
# Returns the number of letters of the alphabet.
#
def alphabet_size
alphabet.size
end
#
# Returns the average degree of states, that is,
# <code>edge_count/state_count</code>
#
def avg_degree
edge_count.to_f/state_count.to_f
end
alias :avg_out_degree :avg_degree
alias :avg_in_degree :avg_degree
#
# Number of accepting states over all states
#
def accepting_ratio
states.select{|s|s.accepting?}.size.to_f/state_count.to_f
end
#
# Number of error states over all states
#
def error_ratio
states.select{|s|s.error?}.size.to_f/state_count.to_f
end
#
# Computes the depth of the automaton.
#
# The depth of an automaton is defined as the length of the longest shortest
# path from the initial state to a state.
#
# This method has a side effect on state marks, as it keeps the depth of
# each state as a mark under _key_, which defaults to :depth.
#
def depth(key = :depth)
algo = Stamina::Utils::Decorate.new
algo.set_suppremum do |d0,d1|
# Unreached state is MAX (i.e. nil is +INF); we look at the min depth for each state
(d0.nil? or d1.nil?) ? (d0 || d1) : (d0 <= d1 ? d0 : d1)
end
algo.set_propagate{|d,e| d+1 }
algo.set_initiator{|s| s.initial? ? 0 : nil }
algo.set_start_predicate{|s| s.initial? }
algo.call(self, key)
deepest = states.max do |s0,s1|
# do not take unreachable states into account: -1 is taken if nil is encountered
(s0[:depth] || -1) <=> (s1[:depth] || -1)
end
deepest[:depth]
end
end # module Metrics
include Metrics
end # class Automaton
end # module Stamina