stamina 0.3.1 → 0.4.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 +24 -0
- data/Gemfile.lock +5 -1
- data/bin/stamina +10 -0
- data/lib/stamina.rb +2 -1
- data/lib/stamina/abbadingo.rb +2 -0
- data/lib/stamina/abbadingo/random_dfa.rb +48 -0
- data/lib/stamina/abbadingo/random_sample.rb +146 -0
- data/lib/stamina/adl.rb +6 -6
- data/lib/stamina/automaton.rb +29 -4
- data/lib/stamina/automaton/complete.rb +36 -0
- data/lib/stamina/automaton/equivalence.rb +55 -0
- data/lib/stamina/automaton/metrics.rb +8 -1
- data/lib/stamina/automaton/minimize.rb +25 -0
- data/lib/stamina/automaton/minimize/hopcroft.rb +116 -0
- data/lib/stamina/automaton/minimize/pitchies.rb +64 -0
- data/lib/stamina/automaton/strip.rb +16 -0
- data/lib/stamina/automaton/walking.rb +46 -19
- data/lib/stamina/command.rb +45 -0
- data/lib/stamina/command/abbadingo_dfa.rb +81 -0
- data/lib/stamina/command/abbadingo_samples.rb +40 -0
- data/lib/stamina/command/adl2dot.rb +71 -0
- data/lib/stamina/command/classify.rb +48 -0
- data/lib/stamina/command/help.rb +27 -0
- data/lib/stamina/command/infer.rb +141 -0
- data/lib/stamina/command/metrics.rb +51 -0
- data/lib/stamina/command/robustness.rb +22 -0
- data/lib/stamina/command/score.rb +35 -0
- data/lib/stamina/errors.rb +4 -1
- data/lib/stamina/ext/math.rb +20 -0
- data/lib/stamina/induction/{redblue.rb → blue_fringe.rb} +29 -28
- data/lib/stamina/induction/commons.rb +32 -46
- data/lib/stamina/induction/rpni.rb +7 -9
- data/lib/stamina/induction/union_find.rb +3 -3
- data/lib/stamina/loader.rb +1 -0
- data/lib/stamina/sample.rb +79 -2
- data/lib/stamina/scoring.rb +37 -0
- data/lib/stamina/version.rb +2 -2
- data/stamina.gemspec +2 -1
- data/stamina.noespec +9 -12
- data/test/stamina/abbadingo/random_dfa_test.rb +16 -0
- data/test/stamina/abbadingo/random_sample_test.rb +78 -0
- data/test/stamina/adl_test.rb +27 -2
- data/test/stamina/automaton/complete_test.rb +58 -0
- data/test/stamina/automaton/equivalence_test.rb +120 -0
- data/test/stamina/automaton/minimize/hopcroft_test.rb +15 -0
- data/test/stamina/automaton/minimize/minimize_test.rb +55 -0
- data/test/stamina/automaton/minimize/pitchies_test.rb +15 -0
- data/test/stamina/automaton/minimize/rice_edu_10.adl +16 -0
- data/test/stamina/automaton/minimize/rice_edu_10.min.adl +13 -0
- data/test/stamina/automaton/minimize/rice_edu_13.adl +13 -0
- data/test/stamina/automaton/minimize/rice_edu_13.min.adl +7 -0
- data/test/stamina/automaton/minimize/should_strip_1.adl +8 -0
- data/test/stamina/automaton/minimize/should_strip_1.min.adl +6 -0
- data/test/stamina/automaton/minimize/unknown_1.adl +16 -0
- data/test/stamina/automaton/minimize/unknown_1.min.adl +12 -0
- data/test/stamina/automaton/strip_test.rb +36 -0
- data/test/stamina/automaton/walking/dfa_delta_test.rb +39 -0
- data/test/stamina/automaton_test.rb +13 -1
- data/test/stamina/induction/{redblue_test.rb → blue_fringe_test.rb} +22 -22
- data/test/stamina/sample_test.rb +75 -0
- data/test/stamina/stamina_test.rb +13 -2
- metadata +98 -23
- data/bin/adl2dot +0 -12
- data/bin/classify +0 -12
- data/bin/redblue +0 -12
- data/bin/rpni +0 -12
- data/lib/stamina/command/adl2dot_command.rb +0 -73
- data/lib/stamina/command/classify_command.rb +0 -57
- data/lib/stamina/command/redblue_command.rb +0 -58
- data/lib/stamina/command/rpni_command.rb +0 -58
- data/lib/stamina/command/stamina_command.rb +0 -79
data/bin/adl2dot
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__),'..','lib')
|
3
|
-
require "stamina"
|
4
|
-
require "stamina/command/adl2dot_command"
|
5
|
-
begin
|
6
|
-
Stamina::Command::Adl2DotCommand.new.main(ARGV)
|
7
|
-
rescue => ex
|
8
|
-
puts "Internal error occured, sorry for the inconvenience."
|
9
|
-
puts "If the problem persists, please contact Stamina developpers with the \
|
10
|
-
following backtrace:"
|
11
|
-
raise ex
|
12
|
-
end
|
data/bin/classify
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__),'..','lib')
|
3
|
-
require "stamina"
|
4
|
-
require "stamina/command/classify_command"
|
5
|
-
begin
|
6
|
-
Stamina::Command::ClassifyCommand.new.main(ARGV)
|
7
|
-
rescue => ex
|
8
|
-
puts "Internal error occured, sorry for the inconvenience."
|
9
|
-
puts "If the problem persists, please contact Stamina developpers with the \
|
10
|
-
following backtrace:"
|
11
|
-
raise ex
|
12
|
-
end
|
data/bin/redblue
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__),'..','lib')
|
3
|
-
require "stamina"
|
4
|
-
require "stamina/command/redblue_command"
|
5
|
-
begin
|
6
|
-
Stamina::Command::RedBlueCommand.new.main(ARGV)
|
7
|
-
rescue => ex
|
8
|
-
puts "Internal error occured, sorry for the inconvenience."
|
9
|
-
puts "If the problem persists, please contact Stamina developpers with the \
|
10
|
-
following backtrace:"
|
11
|
-
raise ex
|
12
|
-
end
|
data/bin/rpni
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__),'..','lib')
|
3
|
-
require "stamina"
|
4
|
-
require "stamina/command/rpni_command"
|
5
|
-
begin
|
6
|
-
Stamina::Command::RPNICommand.new.main(ARGV)
|
7
|
-
rescue => ex
|
8
|
-
puts "Internal error occured, sorry for the inconvenience."
|
9
|
-
puts "If the problem persists, please contact Stamina developpers with the \
|
10
|
-
following backtrace:"
|
11
|
-
raise ex
|
12
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
require 'stamina/command/stamina_command'
|
2
|
-
module Stamina
|
3
|
-
module Command
|
4
|
-
|
5
|
-
# Implementation of the adl2dot command line tool
|
6
|
-
class Adl2DotCommand < StaminaCommand
|
7
|
-
|
8
|
-
# Gif output instead of dot?
|
9
|
-
attr_reader :gif_output
|
10
|
-
|
11
|
-
# Creates a score command instance
|
12
|
-
def initialize
|
13
|
-
super("adl2dot", "[options] automaton.adl",
|
14
|
-
"Prints an automaton expressed in ADL in dot (or gif) format")
|
15
|
-
@gif_output = false
|
16
|
-
end
|
17
|
-
|
18
|
-
# Installs additional options
|
19
|
-
def options
|
20
|
-
super do |opt|
|
21
|
-
opt.on("-o", "--output=OUTPUT",
|
22
|
-
"Flush result output file") do |value|
|
23
|
-
assert_writable_file(value)
|
24
|
-
@output_file = value
|
25
|
-
end
|
26
|
-
opt.on("-g", "--gif",
|
27
|
-
"Generates a gif file instead of a dot one") do
|
28
|
-
@gif_output = true
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Sets the automaton file
|
34
|
-
def automaton_file=(file)
|
35
|
-
assert_readable_file(file)
|
36
|
-
@automaton_file = file
|
37
|
-
@automaton = Stamina::ADL.parse_automaton_file(file)
|
38
|
-
rescue Stamina::ADL::ParseError
|
39
|
-
raise ArgumentError, "#{file} is not a valid ADL automaton file"
|
40
|
-
end
|
41
|
-
|
42
|
-
# Returns the output file to use
|
43
|
-
def output_file
|
44
|
-
@output_file || "#{File.basename(@automaton_file, '.adl')}.#{gif_output ? 'gif' : 'dot'}"
|
45
|
-
end
|
46
|
-
|
47
|
-
# Executes the command
|
48
|
-
def main(argv)
|
49
|
-
parse(argv, :automaton_file)
|
50
|
-
|
51
|
-
# create a file for the dot output
|
52
|
-
if gif_output
|
53
|
-
require 'tempfile'
|
54
|
-
dotfile = Tempfile.new("stamina").path
|
55
|
-
else
|
56
|
-
dotfile = output_file
|
57
|
-
end
|
58
|
-
|
59
|
-
# Flush automaton inside it
|
60
|
-
File.open(dotfile, 'w') do |f|
|
61
|
-
f << Stamina::ADL.parse_automaton_file(@automaton_file).to_dot
|
62
|
-
end
|
63
|
-
|
64
|
-
# if gif output, use dot to convert it
|
65
|
-
if gif_output
|
66
|
-
`dot -Tgif -o #{output_file} #{dotfile}`
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
end # class ScoreCommand
|
71
|
-
|
72
|
-
end # module Command
|
73
|
-
end # module Stamina
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'stamina/command/stamina_command'
|
2
|
-
require 'stamina/induction/rpni'
|
3
|
-
module Stamina
|
4
|
-
module Command
|
5
|
-
|
6
|
-
# Implementation of the classify command line tool
|
7
|
-
class ClassifyCommand < StaminaCommand
|
8
|
-
|
9
|
-
# Creates a score command instance
|
10
|
-
def initialize
|
11
|
-
super("classify", "[options] sample.adl automaton.adl",
|
12
|
-
"Classify a sample using an automaton, both expressed in ADL")
|
13
|
-
end
|
14
|
-
|
15
|
-
# Installs additional options
|
16
|
-
def options
|
17
|
-
super do |opt|
|
18
|
-
opt.on("-o", "--output=OUTPUT",
|
19
|
-
"Flush classification signature in output file") do |value|
|
20
|
-
assert_writable_file(value)
|
21
|
-
@output_file = value
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Sets the sample file
|
27
|
-
def sample_file=(file)
|
28
|
-
assert_readable_file(file)
|
29
|
-
@sample = Stamina::ADL.parse_sample_file(file)
|
30
|
-
rescue Stamina::ADL::ParseError
|
31
|
-
raise ArgumentError, "#{file} is not a valid ADL sample file"
|
32
|
-
end
|
33
|
-
|
34
|
-
# Sets the automaton file
|
35
|
-
def automaton_file=(file)
|
36
|
-
assert_readable_file(file)
|
37
|
-
@automaton = Stamina::ADL.parse_automaton_file(file)
|
38
|
-
rescue Stamina::ADL::ParseError
|
39
|
-
raise ArgumentError, "#{file} is not a valid ADL automaton file"
|
40
|
-
end
|
41
|
-
|
42
|
-
# Executes the command
|
43
|
-
def main(argv)
|
44
|
-
parse(argv, :sample_file, :automaton_file)
|
45
|
-
if @output_file
|
46
|
-
File.open(@output_file, 'w') do |file|
|
47
|
-
file << @automaton.signature(@sample) << "\n"
|
48
|
-
end
|
49
|
-
else
|
50
|
-
STDOUT << @automaton.signature(@sample) << "\n"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
end # class ClassifyCommand
|
55
|
-
|
56
|
-
end # module Command
|
57
|
-
end # module Stamina
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'stamina/command/stamina_command'
|
2
|
-
require 'stamina/induction/redblue'
|
3
|
-
module Stamina
|
4
|
-
module Command
|
5
|
-
|
6
|
-
# Implementation of the redblue command line tool
|
7
|
-
class RedBlueCommand < StaminaCommand
|
8
|
-
|
9
|
-
# Creates a score command instance
|
10
|
-
def initialize
|
11
|
-
super("redblue", "[options] sample.adl",
|
12
|
-
"Executes RedBlue (Regular Positive and Negative Inference) on a ADL sample and\n"\
|
13
|
-
"flushes the induced DFA on the standard output in ADL format as well")
|
14
|
-
end
|
15
|
-
|
16
|
-
# Installs additional options
|
17
|
-
def options
|
18
|
-
super do |opt|
|
19
|
-
opt.on("-v", "--verbose", "Verbose mode") do
|
20
|
-
@verbose = true
|
21
|
-
end
|
22
|
-
opt.on("-o", "--output=OUTPUT",
|
23
|
-
"Flush induced DFA in output file") do |value|
|
24
|
-
assert_writable_file(value)
|
25
|
-
@output_file = value
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Sets the sample file
|
31
|
-
def sample_file=(file)
|
32
|
-
assert_readable_file(file)
|
33
|
-
puts "Parsing sample and building PTA" if @verbose
|
34
|
-
@sample = Stamina::ADL.parse_sample_file(file)
|
35
|
-
rescue Stamina::ADL::ParseError
|
36
|
-
raise ArgumentError, "#{file} is not a valid ADL sample file"
|
37
|
-
end
|
38
|
-
|
39
|
-
# Executes the command
|
40
|
-
def main(argv)
|
41
|
-
parse(argv, :sample_file)
|
42
|
-
t1 = Time.now
|
43
|
-
dfa = Stamina::Induction::RedBlue.execute(@sample, {:verbose => @verbose})
|
44
|
-
t2 = Time.now
|
45
|
-
if @output_file
|
46
|
-
File.open(@output_file, 'w') do |file|
|
47
|
-
Stamina::ADL.print_automaton(dfa, file)
|
48
|
-
end
|
49
|
-
else
|
50
|
-
Stamina::ADL.print_automaton(dfa, STDOUT)
|
51
|
-
end
|
52
|
-
puts "Executed in #{t2-t1} sec" if @verbose
|
53
|
-
end
|
54
|
-
|
55
|
-
end # class ScoreCommand
|
56
|
-
|
57
|
-
end # module Command
|
58
|
-
end # module Stamina
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'stamina/command/stamina_command'
|
2
|
-
require 'stamina/induction/rpni'
|
3
|
-
module Stamina
|
4
|
-
module Command
|
5
|
-
|
6
|
-
# Implementation of the rpni command line tool
|
7
|
-
class RPNICommand < StaminaCommand
|
8
|
-
|
9
|
-
# Creates a score command instance
|
10
|
-
def initialize
|
11
|
-
super("rpni", "[options] sample.adl",
|
12
|
-
"Executes RPNI (Regular Positive and Negative Inference) on a ADL sample and\n"\
|
13
|
-
"flushes the induced DFA on the standard output in ADL format as well")
|
14
|
-
end
|
15
|
-
|
16
|
-
# Installs additional options
|
17
|
-
def options
|
18
|
-
super do |opt|
|
19
|
-
opt.on("-v", "--verbose", "Verbose mode") do
|
20
|
-
@verbose = true
|
21
|
-
end
|
22
|
-
opt.on("-o", "--output=OUTPUT",
|
23
|
-
"Flush induced DFA in output file") do |value|
|
24
|
-
assert_writable_file(value)
|
25
|
-
@output_file = value
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Sets the sample file
|
31
|
-
def sample_file=(file)
|
32
|
-
assert_readable_file(file)
|
33
|
-
puts "Parsing sample and building PTA" if @verbose
|
34
|
-
@sample = Stamina::ADL.parse_sample_file(file)
|
35
|
-
rescue Stamina::ADL::ParseError
|
36
|
-
raise ArgumentError, "#{file} is not a valid ADL sample file"
|
37
|
-
end
|
38
|
-
|
39
|
-
# Executes the command
|
40
|
-
def main(argv)
|
41
|
-
parse(argv, :sample_file)
|
42
|
-
t1 = Time.now
|
43
|
-
dfa = Stamina::Induction::RPNI.execute(@sample, {:verbose => @verbose})
|
44
|
-
t2 = Time.now
|
45
|
-
if @output_file
|
46
|
-
File.open(@output_file, 'w') do |file|
|
47
|
-
Stamina::ADL.print_automaton(dfa, file)
|
48
|
-
end
|
49
|
-
else
|
50
|
-
Stamina::ADL.print_automaton(dfa, STDOUT)
|
51
|
-
end
|
52
|
-
puts "Executed in #{t2-t1} sec" if @verbose
|
53
|
-
end
|
54
|
-
|
55
|
-
end # class ScoreCommand
|
56
|
-
|
57
|
-
end # module Command
|
58
|
-
end # module Stamina
|
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'stamina'
|
2
|
-
require 'optparse'
|
3
|
-
module Stamina
|
4
|
-
module Command
|
5
|
-
|
6
|
-
# Helper to create stamina commands
|
7
|
-
class StaminaCommand
|
8
|
-
|
9
|
-
# Command name
|
10
|
-
attr_reader :name
|
11
|
-
|
12
|
-
# Command description
|
13
|
-
attr_reader :description
|
14
|
-
|
15
|
-
# Command usage
|
16
|
-
attr_reader :usage
|
17
|
-
|
18
|
-
# Creates a command with a name, usage and description
|
19
|
-
def initialize(name, usage, description)
|
20
|
-
@name = name
|
21
|
-
@usage = usage
|
22
|
-
@description = description
|
23
|
-
end
|
24
|
-
|
25
|
-
# Creates options
|
26
|
-
def options(&block)
|
27
|
-
OptionParser.new do |opt|
|
28
|
-
opt.program_name = name
|
29
|
-
opt.version = Stamina::VERSION
|
30
|
-
opt.release = nil
|
31
|
-
opt.summary_indent = ' ' * 4
|
32
|
-
banner = <<-EOF
|
33
|
-
# usage: #{opt.program_name} #{usage}
|
34
|
-
# #{description}
|
35
|
-
EOF
|
36
|
-
opt.banner = banner.gsub(/[ \t]+# /, "")
|
37
|
-
block.call(opt) if block
|
38
|
-
opt.on_tail("-h", "--help", "Show this message") do
|
39
|
-
puts opt
|
40
|
-
exit
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Prints usage (and optionnaly exits)
|
46
|
-
def show_usage(and_exit=true)
|
47
|
-
puts options
|
48
|
-
Kernel.exit if and_exit
|
49
|
-
end
|
50
|
-
|
51
|
-
# Checks that a given file is readable or raises an ArgumentError
|
52
|
-
def assert_readable_file(file)
|
53
|
-
raise ArgumentError, "File #{file} does not exists" unless File.exists?(file)
|
54
|
-
raise ArgumentError, "File #{file} cannot be read" unless File.readable?(file)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Checks that a given file is writable or raises an ArgumentError
|
58
|
-
def assert_writable_file(file)
|
59
|
-
raise ArgumentError, "File #{file} cannot be written" \
|
60
|
-
unless not(File.exists?(file)) or File.writable?(file)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Parses arguments and install last argument as instance variables
|
64
|
-
def parse(argv, *variables)
|
65
|
-
rest = options.parse(argv)
|
66
|
-
show_usage(true) unless rest.size==variables.size
|
67
|
-
variables.each_with_index do |var,i|
|
68
|
-
self.send("#{var}=".to_sym, rest[i])
|
69
|
-
end
|
70
|
-
rescue ArgumentError => ex
|
71
|
-
puts ex.message
|
72
|
-
puts
|
73
|
-
show_usage(true)
|
74
|
-
end
|
75
|
-
|
76
|
-
end # class StaminaCommand
|
77
|
-
|
78
|
-
end # module Command
|
79
|
-
end # module Stamina
|