stamina 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +22 -5
- data/LICENCE.md +2 -2
- data/bin/stamina +1 -7
- data/lib/stamina.rb +10 -19
- metadata +54 -333
- data/.gemtest +0 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +0 -37
- data/Manifest.txt +0 -16
- data/README.md +0 -78
- data/Rakefile +0 -23
- data/example/adl/automaton.adl +0 -49
- data/example/adl/sample.adl +0 -53
- data/example/basic/characteristic_sample.adl +0 -32
- data/example/basic/target.adl +0 -9
- data/example/competition/31_test.adl +0 -1500
- data/example/competition/31_training.adl +0 -1759
- data/lib/stamina/abbadingo.rb +0 -2
- data/lib/stamina/abbadingo/random_dfa.rb +0 -48
- data/lib/stamina/abbadingo/random_sample.rb +0 -146
- data/lib/stamina/adl.rb +0 -298
- data/lib/stamina/automaton.rb +0 -1263
- data/lib/stamina/automaton/complete.rb +0 -36
- data/lib/stamina/automaton/equivalence.rb +0 -55
- data/lib/stamina/automaton/metrics.rb +0 -78
- data/lib/stamina/automaton/minimize.rb +0 -25
- data/lib/stamina/automaton/minimize/hopcroft.rb +0 -116
- data/lib/stamina/automaton/minimize/pitchies.rb +0 -64
- data/lib/stamina/automaton/strip.rb +0 -16
- data/lib/stamina/automaton/walking.rb +0 -363
- data/lib/stamina/classifier.rb +0 -52
- data/lib/stamina/command.rb +0 -45
- data/lib/stamina/command/abbadingo_dfa.rb +0 -81
- data/lib/stamina/command/abbadingo_samples.rb +0 -40
- data/lib/stamina/command/adl2dot.rb +0 -71
- data/lib/stamina/command/classify.rb +0 -48
- data/lib/stamina/command/help.rb +0 -27
- data/lib/stamina/command/infer.rb +0 -141
- data/lib/stamina/command/metrics.rb +0 -51
- data/lib/stamina/command/robustness.rb +0 -22
- data/lib/stamina/command/score.rb +0 -35
- data/lib/stamina/errors.rb +0 -23
- data/lib/stamina/ext/math.rb +0 -20
- data/lib/stamina/induction/blue_fringe.rb +0 -265
- data/lib/stamina/induction/commons.rb +0 -156
- data/lib/stamina/induction/rpni.rb +0 -186
- data/lib/stamina/induction/union_find.rb +0 -377
- data/lib/stamina/input_string.rb +0 -123
- data/lib/stamina/loader.rb +0 -1
- data/lib/stamina/markable.rb +0 -42
- data/lib/stamina/sample.rb +0 -267
- data/lib/stamina/scoring.rb +0 -213
- data/lib/stamina/utils.rb +0 -1
- data/lib/stamina/utils/decorate.rb +0 -81
- data/lib/stamina/version.rb +0 -14
- data/stamina.gemspec +0 -191
- data/stamina.noespec +0 -32
- data/tasks/debug_mail.rake +0 -78
- data/tasks/debug_mail.txt +0 -13
- data/tasks/gem.rake +0 -68
- data/tasks/spec_test.rake +0 -79
- data/tasks/unit_test.rake +0 -77
- data/tasks/yard.rake +0 -51
- data/test/stamina/abbadingo/random_dfa_test.rb +0 -16
- data/test/stamina/abbadingo/random_sample_test.rb +0 -78
- data/test/stamina/adl_test.rb +0 -516
- data/test/stamina/automaton/classifier_test.rb +0 -259
- data/test/stamina/automaton/complete_test.rb +0 -58
- data/test/stamina/automaton/equivalence_test.rb +0 -120
- data/test/stamina/automaton/metrics_test.rb +0 -36
- data/test/stamina/automaton/minimize/hopcroft_test.rb +0 -15
- data/test/stamina/automaton/minimize/minimize_test.rb +0 -55
- data/test/stamina/automaton/minimize/pitchies_test.rb +0 -15
- data/test/stamina/automaton/minimize/rice_edu_10.adl +0 -16
- data/test/stamina/automaton/minimize/rice_edu_10.min.adl +0 -13
- data/test/stamina/automaton/minimize/rice_edu_13.adl +0 -13
- data/test/stamina/automaton/minimize/rice_edu_13.min.adl +0 -7
- data/test/stamina/automaton/minimize/should_strip_1.adl +0 -8
- data/test/stamina/automaton/minimize/should_strip_1.min.adl +0 -6
- data/test/stamina/automaton/minimize/unknown_1.adl +0 -16
- data/test/stamina/automaton/minimize/unknown_1.min.adl +0 -12
- data/test/stamina/automaton/strip_test.rb +0 -36
- data/test/stamina/automaton/to_dot_test.rb +0 -64
- data/test/stamina/automaton/walking/dfa_delta_test.rb +0 -39
- data/test/stamina/automaton/walking_test.rb +0 -206
- data/test/stamina/automaton_additional_test.rb +0 -190
- data/test/stamina/automaton_test.rb +0 -1104
- data/test/stamina/exit.rb +0 -3
- data/test/stamina/induction/blue_fringe_test.rb +0 -83
- data/test/stamina/induction/induction_test.rb +0 -70
- data/test/stamina/induction/redblue_mergesamestatebug_expected.adl +0 -19
- data/test/stamina/induction/redblue_mergesamestatebug_pta.dot +0 -64
- data/test/stamina/induction/redblue_mergesamestatebug_sample.adl +0 -9
- data/test/stamina/induction/redblue_universal_expected.adl +0 -4
- data/test/stamina/induction/redblue_universal_sample.adl +0 -5
- data/test/stamina/induction/rpni_inria_expected.adl +0 -7
- data/test/stamina/induction/rpni_inria_sample.adl +0 -9
- data/test/stamina/induction/rpni_test.rb +0 -129
- data/test/stamina/induction/rpni_test_pta.dot +0 -22
- data/test/stamina/induction/rpni_universal_expected.adl +0 -4
- data/test/stamina/induction/rpni_universal_sample.adl +0 -4
- data/test/stamina/induction/union_find_test.rb +0 -124
- data/test/stamina/input_string_test.rb +0 -323
- data/test/stamina/markable_test.rb +0 -70
- data/test/stamina/randdfa.adl +0 -66
- data/test/stamina/sample.adl +0 -4
- data/test/stamina/sample_classify_test.rb +0 -149
- data/test/stamina/sample_test.rb +0 -290
- data/test/stamina/scoring_test.rb +0 -63
- data/test/stamina/small_dfa.dot +0 -16
- data/test/stamina/small_dfa.gif +0 -0
- data/test/stamina/small_nfa.dot +0 -18
- data/test/stamina/small_nfa.gif +0 -0
- data/test/stamina/stamina_test.rb +0 -80
- data/test/stamina/utils/decorate_test.rb +0 -65
- data/test/test_all.rb +0 -7
data/lib/stamina/classifier.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
module Stamina
|
2
|
-
#
|
3
|
-
# Provides a reusable module for binary classifiers. Classes including this
|
4
|
-
# module are required to provide a label_of(string) method, returning '1' for
|
5
|
-
# strings considered positive, and '0' fr strings considered negative.
|
6
|
-
#
|
7
|
-
# Note that an Automaton being a classifier it already includes this module.
|
8
|
-
#
|
9
|
-
module Classifier
|
10
|
-
|
11
|
-
#
|
12
|
-
# Computes a signature for a given sample (that is, an ordered set of strings).
|
13
|
-
# The signature is a string containing 1 (considered positive, or accepted)
|
14
|
-
# and 0 (considered negative, or rejected), one for each string.
|
15
|
-
#
|
16
|
-
def signature(sample)
|
17
|
-
signature = ''
|
18
|
-
sample.each do |str|
|
19
|
-
signature << label_of(str)
|
20
|
-
end
|
21
|
-
signature
|
22
|
-
end
|
23
|
-
alias :classification_signature :signature
|
24
|
-
|
25
|
-
#
|
26
|
-
# Classifies a sample then compute the classification scoring that is obtained
|
27
|
-
# by comparing the signature obtained by classification and the one of the sample
|
28
|
-
# itself. Returns an object responding to methods defined in Scoring module.
|
29
|
-
#
|
30
|
-
# This method is actually a convenient shortcut for:
|
31
|
-
#
|
32
|
-
# Stamina::Scoring.scoring(signature(sample), sample.signature)
|
33
|
-
#
|
34
|
-
def scoring(sample)
|
35
|
-
Stamina::Scoring.scoring(signature(sample), sample.signature)
|
36
|
-
end
|
37
|
-
alias :classification_scoring :scoring
|
38
|
-
|
39
|
-
#
|
40
|
-
# Checks if a labeled sample is correctly classified by the classifier.
|
41
|
-
#
|
42
|
-
def correctly_classify?(sample)
|
43
|
-
sample.each do |str|
|
44
|
-
label = label_of(str)
|
45
|
-
expected = (str.positive? ? '1' : '0')
|
46
|
-
return false unless expected==label
|
47
|
-
end
|
48
|
-
true
|
49
|
-
end
|
50
|
-
|
51
|
-
end # module Classifier
|
52
|
-
end # module Stamina
|
data/lib/stamina/command.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'stamina'
|
2
|
-
module Stamina
|
3
|
-
#
|
4
|
-
# Stamina - A Ruby Automaton & Induction Toolkit
|
5
|
-
#
|
6
|
-
# SYNOPSIS
|
7
|
-
# #{program_name} [--version] [--help] COMMAND [cmd opts] ARGS...
|
8
|
-
#
|
9
|
-
# OPTIONS
|
10
|
-
# #{summarized_options}
|
11
|
-
#
|
12
|
-
# COMMANDS
|
13
|
-
# #{summarized_subcommands}
|
14
|
-
#
|
15
|
-
# See '#{program_name} help COMMAND' for more information on a specific command.
|
16
|
-
#
|
17
|
-
class Command < ::Quickl::Delegator(__FILE__, __LINE__)
|
18
|
-
|
19
|
-
# Install options
|
20
|
-
options do |opt|
|
21
|
-
|
22
|
-
# Show the help and exit
|
23
|
-
opt.on_tail("--help", "Show help") do
|
24
|
-
raise Quickl::Help
|
25
|
-
end
|
26
|
-
|
27
|
-
# Show version and exit
|
28
|
-
opt.on_tail("--version", "Show version") do
|
29
|
-
raise Quickl::Exit, "#{program_name} #{VERSION} (c) 2010-2011, Bernard Lambeau"
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
end # class Command
|
35
|
-
end # module Stamina
|
36
|
-
require 'stamina/command/robustness'
|
37
|
-
require 'stamina/command/help'
|
38
|
-
require 'stamina/command/adl2dot'
|
39
|
-
require 'stamina/command/metrics'
|
40
|
-
require 'stamina/command/classify'
|
41
|
-
require 'stamina/command/score'
|
42
|
-
require 'stamina/command/abbadingo_dfa'
|
43
|
-
require 'stamina/command/abbadingo_samples'
|
44
|
-
require 'stamina/command/infer'
|
45
|
-
|
@@ -1,81 +0,0 @@
|
|
1
|
-
module Stamina
|
2
|
-
class Command
|
3
|
-
#
|
4
|
-
# Generates a DFA following Abbadingo's protocol
|
5
|
-
#
|
6
|
-
# SYNOPSIS
|
7
|
-
# #{program_name} #{command_name}
|
8
|
-
#
|
9
|
-
# OPTIONS
|
10
|
-
# #{summarized_options}
|
11
|
-
#
|
12
|
-
class AbbadingoDfa < Quickl::Command(__FILE__, __LINE__)
|
13
|
-
include Robustness
|
14
|
-
|
15
|
-
# Size of the target automaton
|
16
|
-
attr_accessor :size
|
17
|
-
|
18
|
-
# Tolerance on the size
|
19
|
-
attr_accessor :size_tolerance
|
20
|
-
|
21
|
-
# Tolerance on the automaton depth
|
22
|
-
attr_accessor :depth_tolerance
|
23
|
-
|
24
|
-
# Where to flush the dfa
|
25
|
-
attr_accessor :output_file
|
26
|
-
|
27
|
-
# Install options
|
28
|
-
options do |opt|
|
29
|
-
|
30
|
-
@size = 64
|
31
|
-
opt.on("--size=X", Integer, "Sets the size of the automaton to generate") do |x|
|
32
|
-
@size = x
|
33
|
-
end
|
34
|
-
|
35
|
-
@size_tolerance = nil
|
36
|
-
opt.on("--size-tolerance[=X]", Integer, "Sets the tolerance on automaton size (in number of states)") do |x|
|
37
|
-
@size_tolerance = x
|
38
|
-
end
|
39
|
-
|
40
|
-
@depth_tolerance = 0
|
41
|
-
opt.on("--depth-tolerance[=X]", Integer, "Sets the tolerance on expected automaton depth (in length, 0 by default)") do |x|
|
42
|
-
@depth_tolerance = x
|
43
|
-
end
|
44
|
-
|
45
|
-
@output_file = nil
|
46
|
-
opt.on("-o", "--output=OUTPUT",
|
47
|
-
"Flush DFA in output file") do |value|
|
48
|
-
@output_file = assert_writable_file(value)
|
49
|
-
end
|
50
|
-
|
51
|
-
end # options
|
52
|
-
|
53
|
-
def accept?(dfa)
|
54
|
-
(size_tolerance.nil? || (size - dfa.state_count).abs <= size_tolerance) &&
|
55
|
-
(depth_tolerance.nil? || ((2*Math.log2(size)-2) - dfa.depth).abs <= depth_tolerance)
|
56
|
-
end
|
57
|
-
|
58
|
-
# Command execution
|
59
|
-
def execute(args)
|
60
|
-
require 'stamina/abbadingo'
|
61
|
-
|
62
|
-
# generate it
|
63
|
-
randomizer = Stamina::Abbadingo::RandomDFA.new(size)
|
64
|
-
begin
|
65
|
-
dfa = randomizer.execute
|
66
|
-
end until accept?(dfa)
|
67
|
-
|
68
|
-
# flush it
|
69
|
-
if output_file
|
70
|
-
File.open(output_file, 'w') do |file|
|
71
|
-
Stamina::ADL.print_automaton(dfa, file)
|
72
|
-
end
|
73
|
-
else
|
74
|
-
Stamina::ADL.print_automaton(dfa, $stdout)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
end # class AbbadingoDFA
|
79
|
-
end # class Command
|
80
|
-
end # module Stamina
|
81
|
-
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Stamina
|
2
|
-
class Command
|
3
|
-
#
|
4
|
-
# Generates samples following Abbadingo's protocol
|
5
|
-
#
|
6
|
-
# SYNOPSIS
|
7
|
-
# #{program_name} #{command_name} target.adl
|
8
|
-
#
|
9
|
-
# OPTIONS
|
10
|
-
# #{summarized_options}
|
11
|
-
#
|
12
|
-
class AbbadingoSamples < Quickl::Command(__FILE__, __LINE__)
|
13
|
-
|
14
|
-
# Install options
|
15
|
-
options do |opt|
|
16
|
-
|
17
|
-
end # options
|
18
|
-
|
19
|
-
# Command execution
|
20
|
-
def execute(args)
|
21
|
-
raise Quickl::Help unless args.size == 1
|
22
|
-
|
23
|
-
# Loads the target automaton
|
24
|
-
target_file = args.first
|
25
|
-
basename = File.basename(target_file, '.adl')
|
26
|
-
dirname = File.dirname(target_file)
|
27
|
-
target = Stamina::ADL::parse_automaton_file(target_file)
|
28
|
-
|
29
|
-
require 'stamina/abbadingo'
|
30
|
-
training, test = Stamina::Abbadingo::RandomSample.execute(target)
|
31
|
-
|
32
|
-
# Flush results aside the target automaton file
|
33
|
-
Stamina::ADL::print_sample_in_file(training, File.join(dirname, "#{basename}-training.adl"))
|
34
|
-
Stamina::ADL::print_sample_in_file(test, File.join(dirname, "#{basename}-test.adl"))
|
35
|
-
end
|
36
|
-
|
37
|
-
end # class AbbadingoSamples
|
38
|
-
end # class Command
|
39
|
-
end # module Stamina
|
40
|
-
|
@@ -1,71 +0,0 @@
|
|
1
|
-
module Stamina
|
2
|
-
class Command
|
3
|
-
#
|
4
|
-
# Prints an automaton expressed in ADL in dot (or gif) format
|
5
|
-
#
|
6
|
-
# SYNOPSIS
|
7
|
-
# #{program_name} #{command_name} automaton.adl
|
8
|
-
#
|
9
|
-
# OPTIONS
|
10
|
-
# #{summarized_options}
|
11
|
-
#
|
12
|
-
class Adl2dot < Quickl::Command(__FILE__, __LINE__)
|
13
|
-
include Robustness
|
14
|
-
|
15
|
-
attr_reader :gif_output
|
16
|
-
|
17
|
-
# Install options
|
18
|
-
options do |opt|
|
19
|
-
|
20
|
-
@output_file = nil
|
21
|
-
opt.on("-o", "--output=OUTPUT",
|
22
|
-
"Flush result output file") do |value|
|
23
|
-
@output_file = assert_writable_file(value)
|
24
|
-
end
|
25
|
-
|
26
|
-
opt.on("-g", "--gif",
|
27
|
-
"Generates a gif file instead of a dot one") do
|
28
|
-
@gif_output = true
|
29
|
-
end
|
30
|
-
|
31
|
-
end # options
|
32
|
-
|
33
|
-
def output_file(infile)
|
34
|
-
@output_file || "#{File.basename(infile || 'stdin.adl', '.adl')}.#{gif_output ? 'gif' : 'dot'}"
|
35
|
-
end
|
36
|
-
|
37
|
-
# Command execution
|
38
|
-
def execute(args)
|
39
|
-
raise Quickl::Help unless args.size <= 1
|
40
|
-
|
41
|
-
# Loads the target automaton
|
42
|
-
input = if args.size == 1
|
43
|
-
File.read assert_readable_file(args.first)
|
44
|
-
else
|
45
|
-
$stdin.readlines.join("\n")
|
46
|
-
end
|
47
|
-
automaton = Stamina::ADL::parse_automaton(input)
|
48
|
-
|
49
|
-
# create a file for the dot output
|
50
|
-
if gif_output
|
51
|
-
require 'tempfile'
|
52
|
-
dotfile = Tempfile.new("stamina").path
|
53
|
-
else
|
54
|
-
dotfile = output_file(args.first)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Flush automaton inside it
|
58
|
-
File.open(dotfile, 'w') do |f|
|
59
|
-
f << automaton.to_dot
|
60
|
-
end
|
61
|
-
|
62
|
-
# if gif output, use dot to convert it
|
63
|
-
if gif_output
|
64
|
-
`dot -Tgif -o #{output_file(args.first)} #{dotfile}`
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end # class Adl2dot
|
69
|
-
end # class Command
|
70
|
-
end # module Stamina
|
71
|
-
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module Stamina
|
2
|
-
class Command
|
3
|
-
#
|
4
|
-
# Classifies a sample thanks with an automaton
|
5
|
-
#
|
6
|
-
# SYNOPSIS
|
7
|
-
# #{program_name} #{command_name} sample.adl automaton.adl
|
8
|
-
#
|
9
|
-
# OPTIONS
|
10
|
-
# #{summarized_options}
|
11
|
-
#
|
12
|
-
class Classify < Quickl::Command(__FILE__, __LINE__)
|
13
|
-
include Robustness
|
14
|
-
|
15
|
-
# Where to flush the output
|
16
|
-
attr_accessor :output_file
|
17
|
-
|
18
|
-
# Install options
|
19
|
-
options do |opt|
|
20
|
-
|
21
|
-
@output_file = nil
|
22
|
-
opt.on("-o", "--output=OUTPUT",
|
23
|
-
"Flush classification signature in output file") do |value|
|
24
|
-
assert_writable_file(value)
|
25
|
-
@output_file = value
|
26
|
-
end
|
27
|
-
|
28
|
-
end # options
|
29
|
-
|
30
|
-
# Command execution
|
31
|
-
def execute(args)
|
32
|
-
raise Quickl::Help unless args.size == 2
|
33
|
-
sample = Stamina::ADL::parse_sample_file assert_readable_file(args.first)
|
34
|
-
automaton = Stamina::ADL::parse_automaton_file assert_readable_file(args.last)
|
35
|
-
|
36
|
-
if of = output_file
|
37
|
-
File.open(of, 'w'){|io|
|
38
|
-
io << automaton.signature(sample)
|
39
|
-
}
|
40
|
-
else
|
41
|
-
$stdout << automaton.signature(sample)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
end # class Classify
|
46
|
-
end # class Command
|
47
|
-
end # module Stamina
|
48
|
-
|
data/lib/stamina/command/help.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
module Stamina
|
2
|
-
class Command
|
3
|
-
#
|
4
|
-
# Show help about a specific command
|
5
|
-
#
|
6
|
-
# SYNOPSIS
|
7
|
-
# #{program_name} #{command_name} COMMAND
|
8
|
-
#
|
9
|
-
class Help < Quickl::Command(__FILE__, __LINE__)
|
10
|
-
|
11
|
-
# Let NoSuchCommandError be passed to higher stage
|
12
|
-
no_react_to Quickl::NoSuchCommand
|
13
|
-
|
14
|
-
# Command execution
|
15
|
-
def execute(args)
|
16
|
-
if args.size != 1
|
17
|
-
puts super_command.help
|
18
|
-
else
|
19
|
-
cmd = has_command!(args.first, super_command)
|
20
|
-
puts cmd.help
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end # class Help
|
25
|
-
end # class Command
|
26
|
-
end # module Stamina
|
27
|
-
|
@@ -1,141 +0,0 @@
|
|
1
|
-
module Stamina
|
2
|
-
class Command
|
3
|
-
#
|
4
|
-
# Grammar inference, induces a DFA from a training sample using an
|
5
|
-
# chosen algorithm.
|
6
|
-
#
|
7
|
-
# SYNOPSIS
|
8
|
-
# #{program_name} #{command_name} sample.adl
|
9
|
-
#
|
10
|
-
# OPTIONS
|
11
|
-
# #{summarized_options}
|
12
|
-
#
|
13
|
-
class Infer < Quickl::Command(__FILE__, __LINE__)
|
14
|
-
include Robustness
|
15
|
-
|
16
|
-
attr_accessor :algorithm
|
17
|
-
attr_accessor :take
|
18
|
-
attr_accessor :score
|
19
|
-
attr_accessor :verbose
|
20
|
-
attr_accessor :drop
|
21
|
-
attr_accessor :output_file
|
22
|
-
|
23
|
-
# Install options
|
24
|
-
options do |opt|
|
25
|
-
|
26
|
-
@algorithm = :rpni
|
27
|
-
opt.on("--algorithm=X", "Sets the induction algorithm to use (rpni, bluefringe)") do |x|
|
28
|
-
@algorithm = x.to_sym
|
29
|
-
end
|
30
|
-
|
31
|
-
@take = 1.0
|
32
|
-
opt.on("--take=X", Float, "Take only X% of available strings") do |x|
|
33
|
-
@take = x.to_f
|
34
|
-
unless @take > 0.0 and @take <= 1.0
|
35
|
-
raise Quickl::InvalidOption, "Invalid --take option: #{@take}"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
@score = nil
|
40
|
-
opt.on("--score=test.adl", "Add scoring information to metadata, using test.adl file") do |x|
|
41
|
-
@score = assert_readable_file(x)
|
42
|
-
end
|
43
|
-
|
44
|
-
@verbose = true
|
45
|
-
opt.on("-v", "--[no-]verbose", "Verbose mode") do |x|
|
46
|
-
@verbose = x
|
47
|
-
end
|
48
|
-
|
49
|
-
@drop = false
|
50
|
-
opt.on("-d", "--drop", "Drop result") do |x|
|
51
|
-
@drop = x
|
52
|
-
end
|
53
|
-
|
54
|
-
@output_file = nil
|
55
|
-
opt.on("-o", "--output=OUTPUT",
|
56
|
-
"Flush induced DFA in output file") do |value|
|
57
|
-
@output_file = assert_writable_file(value)
|
58
|
-
end
|
59
|
-
|
60
|
-
end # options
|
61
|
-
|
62
|
-
def launch_induction(sample)
|
63
|
-
require 'benchmark'
|
64
|
-
|
65
|
-
algo_clazz = case algorithm
|
66
|
-
when :rpni
|
67
|
-
Stamina::Induction::RPNI
|
68
|
-
when :bluefringe
|
69
|
-
Stamina::Induction::BlueFringe
|
70
|
-
else
|
71
|
-
raise Quickl::InvalidOption, "Unknown induction algorithm: #{algo}"
|
72
|
-
end
|
73
|
-
|
74
|
-
dfa, tms = nil, nil
|
75
|
-
tms = Benchmark.measure do
|
76
|
-
dfa = algo_clazz.execute(sample, {:verbose => verbose})
|
77
|
-
end
|
78
|
-
[dfa, tms]
|
79
|
-
end
|
80
|
-
|
81
|
-
def load_sample(file)
|
82
|
-
sample = Stamina::ADL.parse_sample_file(file)
|
83
|
-
if @take != 1.0
|
84
|
-
sampled = Stamina::Sample.new
|
85
|
-
sample.each_positive{|s| sampled << s if Kernel.rand < @take}
|
86
|
-
sample.each_negative{|s| sampled << s if Kernel.rand < @take}
|
87
|
-
sample = sampled
|
88
|
-
end
|
89
|
-
sample
|
90
|
-
end
|
91
|
-
|
92
|
-
# Command execution
|
93
|
-
def execute(args)
|
94
|
-
raise Quickl::Help unless args.size == 1
|
95
|
-
|
96
|
-
# Parses the sample
|
97
|
-
$stderr << "Parsing sample...\n" if verbose
|
98
|
-
sample = load_sample(assert_readable_file(args.first))
|
99
|
-
|
100
|
-
# Induce the DFA
|
101
|
-
dfa, tms = launch_induction(sample)
|
102
|
-
|
103
|
-
# Flush result
|
104
|
-
unless drop
|
105
|
-
if output_file
|
106
|
-
File.open(output_file, 'w') do |file|
|
107
|
-
Stamina::ADL.print_automaton(dfa, file)
|
108
|
-
end
|
109
|
-
else
|
110
|
-
Stamina::ADL.print_automaton(dfa, $stdout)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
# build meta information
|
115
|
-
meta = {:algorithm => algorithm,
|
116
|
-
:sample => File.basename(args.first),
|
117
|
-
:take => take,
|
118
|
-
:sample_size => sample.size,
|
119
|
-
:positive_count => sample.positive_count,
|
120
|
-
:negative_count => sample.negative_count,
|
121
|
-
:real_time => tms.real,
|
122
|
-
:total_time => tms.total,
|
123
|
-
:user_time => tms.utime + tms.cutime,
|
124
|
-
:system_time => tms.stime + tms.cstime}
|
125
|
-
|
126
|
-
if score
|
127
|
-
test = Stamina::ADL::parse_sample_file(score)
|
128
|
-
classified_as = dfa.signature(test)
|
129
|
-
reference = test.signature
|
130
|
-
scoring = Scoring.scoring(classified_as, reference)
|
131
|
-
meta.merge!(scoring.to_h)
|
132
|
-
end
|
133
|
-
|
134
|
-
# Display information
|
135
|
-
puts meta.inspect
|
136
|
-
end
|
137
|
-
|
138
|
-
end # class Infer
|
139
|
-
end # class Command
|
140
|
-
end # module Stamina
|
141
|
-
|