nfa2dfa 1.0.2 → 1.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c062458afee68eb899ec35c6fee8e82ea0366cb
4
- data.tar.gz: 9f5191740fba0e5b0b865cd9d3e3b1af3a22856e
3
+ metadata.gz: 0dd869aacabd6004faccc4de1a7f9b35f7ec8b3c
4
+ data.tar.gz: dfe9e1cb14760e786a2b4ea5b0de62620c53e2ba
5
5
  SHA512:
6
- metadata.gz: a4c92af38dc76982b669a26d3ba61b3038fd5f28496f37f4d1f7f6ecaf26565365fdf71e4f42da9e27062501ffe582f98348f9feb58764a0a31e4665f9aa786c
7
- data.tar.gz: 2f1c55ad5e1a8efd8d3ff31bc7b060a063698d30d32ba370fe34d85a796b16df8ef49c940b4438cf0a86c4198aa5e645fc0911a7ad17fd655b940ec78d43c573
6
+ metadata.gz: ecb4a5153853a308678183c024a342d59c1f5a8272398bc03243351656322322959c3acabcdf840c19f62feafb9ec63a74ab087cf881790c222d194364dae20e
7
+ data.tar.gz: bc6bfa2a48abeac27a93521dfe5184a8ff4f1e7a07a407d5ba019027099acf5195e786d6604e9ab9cde6fab834f64b6112244c80259b8e336a65f55261a85feb
data/bin/automaton ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'commander/import'
5
+ require 'nfa2dfa'
6
+ program :version, '0.0.1'
7
+ program :description, 'Controller of automaton'
8
+ program :name, 'automaton'
9
+
10
+ command :create_finite do |c|
11
+ c.syntax = 'automaton create_finite [options]'
12
+ c.description = 'Creates determined automaton from file and writes it into "<input_file>.determined"'
13
+ c.action do |args|
14
+ args.each do |arg|
15
+ input_mat = Nfa2Dfa::Automaton.init(arg)
16
+ output_mat = input_mat.determine
17
+ data = output_mat.to_str
18
+ File.open(arg + ".determined", 'w') { |file| file.write(data) }
19
+ end
20
+ end
21
+ end
22
+
23
+ command :automaton_to_png do |c|
24
+ c.syntax = 'automaton automaton_to_png [options]'
25
+ c.description = 'Creates png representation of automaton from input'
26
+ c.action do |args|
27
+ args.each do |arg|
28
+ input_mat = Nfa2Dfa::Automaton.init(arg)
29
+ data = input_mat.to_graph(arg + ".png")
30
+ end
31
+ end
32
+ end
33
+
data/lib/nfa2dfa.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  module Nfa2Dfa
3
2
  require_relative 'automaton'
4
3
  require_relative 'state'
@@ -0,0 +1,134 @@
1
+ require 'rspec'
2
+ require 'spec_helper'
3
+ require_relative '../lib/automaton.rb'
4
+
5
+ describe Nfa2Dfa::Automaton do
6
+ before(:each) do
7
+ @file_path = "#{File.dirname(__FILE__)}/testdata/valid_input.automat"
8
+ @file_path2 = "#{File.dirname(__FILE__)}/testdata/valid_input2.automat"
9
+ @file_path3 = "#{File.dirname(__FILE__)}/testdata/valid_input3.automat"
10
+ end
11
+ context "initializes as" do
12
+ it "valid automaton" do
13
+ mat = Automaton.init(@file_path)
14
+ mat.should_not eq NIL
15
+ mat.class.should eq Nfa2Dfa::Automaton
16
+ end
17
+ it "invalid automaton, when there is invalid input" do
18
+ mat = Automaton.init("#{File.dirname(__FILE__)}/testdata/invalid_input.automat")
19
+ mat.should eq NIL
20
+ end
21
+ end
22
+ it "should be exportable in same format by method 'to_str'" do
23
+ valid_str = "z f\na b\nz-a-f f-b-f\nz\nf"
24
+ mat = Automaton.init(@file_path)
25
+ mat.to_str.should eq valid_str
26
+ end
27
+
28
+ context "accepts method resolves" do
29
+ subject { Automaton.init(@file_path) }
30
+ it "valid words" do
31
+ (subject.accepts? "a b").should eq true
32
+ (subject.accepts? "a").should eq true
33
+ (subject.accepts? "a b b b").should eq true
34
+ (subject.accepts? "a b b").should eq true
35
+ end
36
+
37
+ it "invalid words" do
38
+ (subject.accepts? "").should eq false
39
+ (subject.accepts? "a a").should eq false
40
+ (subject.accepts? "a a ").should eq false
41
+ (subject.accepts? "a b a").should eq false
42
+ end
43
+ end
44
+
45
+ it "should be able to check if automat is deterministic" do
46
+ Automaton.init(@file_path).deterministic?.should eq true
47
+ Automaton.init(@file_path2).deterministic?.should eq false
48
+ end
49
+
50
+ context "can create deterministic automaton" do
51
+ it "returns Automaton class" do
52
+ mat1 = Automaton.init(@file_path)
53
+ mat2 = Automaton.init(@file_path2)
54
+ mat3 = Automaton.init(@file_path3)
55
+ mat1.determine.class.should eq Nfa2Dfa::Automaton
56
+ mat2.determine.class.should eq Nfa2Dfa::Automaton
57
+ mat3.determine.class.should eq Nfa2Dfa::Automaton
58
+ end
59
+ it "returns same instance of Automaton when already deterministic" do
60
+ mat1 = Automaton.init(@file_path)
61
+ mat1det = mat1.determine
62
+ mat1.should eq mat1det
63
+ end
64
+ it "returns deterministic automaton" do
65
+ mat2 = Automaton.init(@file_path2)
66
+ mat2det = mat2.determine
67
+ mat2det.deterministic?.should eq true
68
+ end
69
+
70
+ it "which can accept same words" do
71
+ mat2 = Automaton.init(@file_path2)
72
+ mat2det = mat2.determine
73
+ word = ""
74
+ (mat2.accepts? word).should eq mat2det.accepts? word
75
+ (mat2.accepts? word).should eq true
76
+ word = "a a"
77
+ (mat2.accepts? word).should eq mat2det.accepts? word
78
+ (mat2.accepts? word).should eq true
79
+ word = "a b"
80
+ (mat2.accepts? word).should eq mat2det.accepts? word
81
+ (mat2.accepts? word).should eq true
82
+ word = "a c"
83
+ (mat2.accepts? word).should eq mat2det.accepts? word
84
+ (mat2.accepts? word).should eq true
85
+ word = "a c c"
86
+ (mat2.accepts? word).should eq mat2det.accepts? word
87
+ (mat2.accepts? word).should eq true
88
+ word = "a c c a"
89
+ (mat2.accepts? word).should eq mat2det.accepts? word
90
+ (mat2.accepts? word).should eq true
91
+ word = "a c c a c a"
92
+ (mat2.accepts? word).should eq mat2det.accepts? word
93
+ (mat2.accepts? word).should eq true
94
+ word = "a c c a c a a b"
95
+ (mat2.accepts? word).should eq mat2det.accepts? word
96
+ (mat2.accepts? word).should eq true
97
+ word = "c a b c a b c"
98
+ (mat2.accepts? word).should eq mat2det.accepts? word
99
+ (mat2.accepts? word).should eq true
100
+ word = "a c c b c"
101
+ (mat2.accepts? word).should eq mat2det.accepts? word
102
+ (mat2.accepts? word).should eq true
103
+ end
104
+
105
+ it "which rejects same words" do
106
+ mat2 = Automaton.init(@file_path3)
107
+ mat2det = mat2.determine
108
+ word = "0"
109
+ (mat2.accepts? word).should eq mat2det.accepts? word
110
+ (mat2.accepts? word).should eq false
111
+ word = "1"
112
+ (mat2.accepts? word).should eq mat2det.accepts? word
113
+ (mat2.accepts? word).should eq false
114
+ word = "0 1"
115
+ (mat2.accepts? word).should eq mat2det.accepts? word
116
+ (mat2.accepts? word).should eq false
117
+ word = "1 0"
118
+ (mat2.accepts? word).should eq mat2det.accepts? word
119
+ (mat2.accepts? word).should eq false
120
+ word = "1 1 1 1 0"
121
+ (mat2.accepts? word).should eq mat2det.accepts? word
122
+ (mat2.accepts? word).should eq false
123
+ word = "0 0 0 0 1"
124
+ (mat2.accepts? word).should eq mat2det.accepts? word
125
+ (mat2.accepts? word).should eq false
126
+ end
127
+
128
+ it "should have method for exporting as GraphViz 'to_graph'" do
129
+ mat = Automaton.init(@file_path2)
130
+ expect(mat.methods.include?(:to_graph)).to be true
131
+ end
132
+ end
133
+ end
134
+
@@ -0,0 +1,101 @@
1
+ require 'rspec'
2
+ require 'spec_helper'
3
+ require_relative '../lib/state.rb'
4
+
5
+ describe Nfa2Dfa::State do
6
+ before(:each) do
7
+ @end_state = State.new("end")
8
+ @end_state.to_starting_node
9
+ end
10
+ context "should keep " do
11
+ subject { State.new("state") }
12
+
13
+ it "basic data" do
14
+ subject.id.should eq "state"
15
+ subject.is_final.should eq false
16
+ end
17
+
18
+ it "transitions as private data" do
19
+ expect { subject.transitions }.to raise_error NoMethodError
20
+ end
21
+
22
+ it "added transitions" do
23
+ trans = Transition.new(subject, "jump", @end_state)
24
+ transes = subject.add_transition(trans)
25
+ transes.size.should eq 1
26
+ transes[0].should eq trans
27
+ end
28
+
29
+ it "cleared transition array" do
30
+ subject.clear_transitions.size.should eq 0
31
+ end
32
+ end
33
+
34
+ it "should be able to be finalized" do
35
+ state_a = State.new("a")
36
+ state_a.is_final.should eq false
37
+ state_a.finalize
38
+ state_a.is_final.should eq true
39
+ state_a.finalize
40
+ state_a.is_final.should eq true
41
+ end
42
+ it "should be able to be starting node" do
43
+ state_a = State.new("a")
44
+ state_a.is_starting.should eq false
45
+ state_a.to_starting_node
46
+ state_a.is_starting.should eq true
47
+ state_a.to_starting_node
48
+ state_a.is_starting.should eq true
49
+ end
50
+
51
+ context "gets correct next state" do
52
+ trans = []
53
+ state_a = State.new("a")
54
+ state_b = State.new("b")
55
+ state_c = State.new("c")
56
+ trans[0] = Transition.new(state_a, "0", state_b)
57
+ trans[1] = Transition.new(state_b, "1", state_a)
58
+ trans[2] = Transition.new(state_a, "0", state_a)
59
+ trans[3] = Transition.new(state_c, "1", state_a)
60
+ trans[4] = Transition.new(state_a, "0", state_c)
61
+ state_a.add_transition(trans[0])
62
+ state_a.add_transition(trans[2])
63
+ state_a.add_transition(trans[4])
64
+ state_b.add_transition(trans[1])
65
+ state_c.add_transition(trans[3])
66
+
67
+ it "array" do
68
+ state_a.get_next("0").size.should eq 3
69
+ state_a.get_next("1").size.should eq 0
70
+ end
71
+
72
+ it "in first step" do
73
+ state_a.get_next("0")[0].should eq state_b
74
+ end
75
+
76
+ it "in second step" do
77
+ state_a.get_next("0")[0].get_next("1")[0].should eq state_a
78
+ end
79
+ end
80
+
81
+ context "while conversion from NFA to DFA" do
82
+ trans = Array.new
83
+ state_a = State.new("a")
84
+ state_b = State.new("b")
85
+ state_c = State.new("c")
86
+ trans[0] = Transition.new(state_a, "0", state_b)
87
+ trans[1] = Transition.new(state_b, "1", state_a)
88
+ trans[2] = Transition.new(state_a, "0", state_a)
89
+ trans[3] = Transition.new(state_c, "1", state_a)
90
+ trans[4] = Transition.new(state_a, "0", state_c)
91
+
92
+ subject { State.new("a,b") }
93
+ it "should find correct transitions" do
94
+ subject.associate_transitions(trans)
95
+ subject.get_next("a").size.should eq 0
96
+ subject.get_next("1").size.should eq 1
97
+ subject.get_next("0").size.should eq 3
98
+ end
99
+ end
100
+ end
101
+
@@ -0,0 +1,28 @@
1
+ require 'rspec'
2
+ require 'spec_helper'
3
+ require_relative '../lib/transition.rb'
4
+
5
+ describe Nfa2Dfa::Transition do
6
+ context "should keep " do
7
+ state1 = State.new("1")
8
+ state2 = State.new("2")
9
+ state2.finalize
10
+ subject { Transition.new(state1, "a", state2) }
11
+
12
+ it "states" do
13
+ subject.beginning_state.should eq state1
14
+ subject.ending_state.should eq state2
15
+ end
16
+
17
+ it "transition alphabet" do
18
+ subject.alphabet.should eq "a"
19
+ end
20
+
21
+ it "correct types" do
22
+ subject.beginning_state.class.should eq State
23
+ subject.ending_state.class.should eq State
24
+ subject.alphabet.class.should eq String
25
+ end
26
+ end
27
+ end
28
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nfa2dfa
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Zachov
@@ -12,7 +12,8 @@ date: 2013-10-15 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Finite automaton determinizer
14
14
  email: martin.zachov@gmail.com
15
- executables: []
15
+ executables:
16
+ - automaton
16
17
  extensions: []
17
18
  extra_rdoc_files: []
18
19
  files:
@@ -20,6 +21,10 @@ files:
20
21
  - lib/automaton.rb
21
22
  - lib/transition.rb
22
23
  - lib/nfa2dfa.rb
24
+ - spec/automaton_spec.rb
25
+ - spec/state_spec.rb
26
+ - spec/transition_spec.rb
27
+ - bin/automaton
23
28
  homepage: http://fit.cvut.cz
24
29
  licenses:
25
30
  - GNU GPL
@@ -44,4 +49,7 @@ rubygems_version: 2.0.3
44
49
  signing_key:
45
50
  specification_version: 4
46
51
  summary: MI-RUB semestral
47
- test_files: []
52
+ test_files:
53
+ - spec/automaton_spec.rb
54
+ - spec/state_spec.rb
55
+ - spec/transition_spec.rb