stamina 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|