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.
Files changed (71) hide show
  1. data/CHANGELOG.md +24 -0
  2. data/Gemfile.lock +5 -1
  3. data/bin/stamina +10 -0
  4. data/lib/stamina.rb +2 -1
  5. data/lib/stamina/abbadingo.rb +2 -0
  6. data/lib/stamina/abbadingo/random_dfa.rb +48 -0
  7. data/lib/stamina/abbadingo/random_sample.rb +146 -0
  8. data/lib/stamina/adl.rb +6 -6
  9. data/lib/stamina/automaton.rb +29 -4
  10. data/lib/stamina/automaton/complete.rb +36 -0
  11. data/lib/stamina/automaton/equivalence.rb +55 -0
  12. data/lib/stamina/automaton/metrics.rb +8 -1
  13. data/lib/stamina/automaton/minimize.rb +25 -0
  14. data/lib/stamina/automaton/minimize/hopcroft.rb +116 -0
  15. data/lib/stamina/automaton/minimize/pitchies.rb +64 -0
  16. data/lib/stamina/automaton/strip.rb +16 -0
  17. data/lib/stamina/automaton/walking.rb +46 -19
  18. data/lib/stamina/command.rb +45 -0
  19. data/lib/stamina/command/abbadingo_dfa.rb +81 -0
  20. data/lib/stamina/command/abbadingo_samples.rb +40 -0
  21. data/lib/stamina/command/adl2dot.rb +71 -0
  22. data/lib/stamina/command/classify.rb +48 -0
  23. data/lib/stamina/command/help.rb +27 -0
  24. data/lib/stamina/command/infer.rb +141 -0
  25. data/lib/stamina/command/metrics.rb +51 -0
  26. data/lib/stamina/command/robustness.rb +22 -0
  27. data/lib/stamina/command/score.rb +35 -0
  28. data/lib/stamina/errors.rb +4 -1
  29. data/lib/stamina/ext/math.rb +20 -0
  30. data/lib/stamina/induction/{redblue.rb → blue_fringe.rb} +29 -28
  31. data/lib/stamina/induction/commons.rb +32 -46
  32. data/lib/stamina/induction/rpni.rb +7 -9
  33. data/lib/stamina/induction/union_find.rb +3 -3
  34. data/lib/stamina/loader.rb +1 -0
  35. data/lib/stamina/sample.rb +79 -2
  36. data/lib/stamina/scoring.rb +37 -0
  37. data/lib/stamina/version.rb +2 -2
  38. data/stamina.gemspec +2 -1
  39. data/stamina.noespec +9 -12
  40. data/test/stamina/abbadingo/random_dfa_test.rb +16 -0
  41. data/test/stamina/abbadingo/random_sample_test.rb +78 -0
  42. data/test/stamina/adl_test.rb +27 -2
  43. data/test/stamina/automaton/complete_test.rb +58 -0
  44. data/test/stamina/automaton/equivalence_test.rb +120 -0
  45. data/test/stamina/automaton/minimize/hopcroft_test.rb +15 -0
  46. data/test/stamina/automaton/minimize/minimize_test.rb +55 -0
  47. data/test/stamina/automaton/minimize/pitchies_test.rb +15 -0
  48. data/test/stamina/automaton/minimize/rice_edu_10.adl +16 -0
  49. data/test/stamina/automaton/minimize/rice_edu_10.min.adl +13 -0
  50. data/test/stamina/automaton/minimize/rice_edu_13.adl +13 -0
  51. data/test/stamina/automaton/minimize/rice_edu_13.min.adl +7 -0
  52. data/test/stamina/automaton/minimize/should_strip_1.adl +8 -0
  53. data/test/stamina/automaton/minimize/should_strip_1.min.adl +6 -0
  54. data/test/stamina/automaton/minimize/unknown_1.adl +16 -0
  55. data/test/stamina/automaton/minimize/unknown_1.min.adl +12 -0
  56. data/test/stamina/automaton/strip_test.rb +36 -0
  57. data/test/stamina/automaton/walking/dfa_delta_test.rb +39 -0
  58. data/test/stamina/automaton_test.rb +13 -1
  59. data/test/stamina/induction/{redblue_test.rb → blue_fringe_test.rb} +22 -22
  60. data/test/stamina/sample_test.rb +75 -0
  61. data/test/stamina/stamina_test.rb +13 -2
  62. metadata +98 -23
  63. data/bin/adl2dot +0 -12
  64. data/bin/classify +0 -12
  65. data/bin/redblue +0 -12
  66. data/bin/rpni +0 -12
  67. data/lib/stamina/command/adl2dot_command.rb +0 -73
  68. data/lib/stamina/command/classify_command.rb +0 -57
  69. data/lib/stamina/command/redblue_command.rb +0 -58
  70. data/lib/stamina/command/rpni_command.rb +0 -58
  71. 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