Class: Fae::FiniteAutomata
- Inherits:
-
Object
- Object
- Fae::FiniteAutomata
- Defined in:
- lib/fae/finite_automata.rb
Overview
The main class that drives the Finite Automata evaluation.
Takes in a language, states, and strings, and checks them to validate a state diagram.
Instance Attribute Summary collapse
-
#description ⇒ Object
readonly
Returns the value of attribute description.
-
#language ⇒ Object
readonly
Returns the value of attribute language.
-
#states ⇒ Object
readonly
Returns the value of attribute states.
-
#strings ⇒ Object
readonly
Returns the value of attribute strings.
-
#valid_block ⇒ Object
Returns the value of attribute valid_block.
Instance Method Summary collapse
-
#add_state(new_state) ⇒ Object
Adds a single state to the states array.
-
#add_states(states) ⇒ Object
Adds strings to check against when evaluating.
-
#add_string(string) ⇒ Object
Adds a single string to the strings array.
-
#add_strings(strings) ⇒ Object
Adds strings to check against when evaluating.
-
#difference(fa) ⇒ Object
Generates the finite automata for the difference of two different finite automatas.
-
#evaluate!(suppress_output = false) ⇒ Object
Runs the evaluation on the finite automata.
-
#generate_strings(number, length) ⇒ Object
Generates strings for the finite automata and adds them to the strings array.
-
#get_state(name) ⇒ Object
Retrieves a state from this finite automata by name.
-
#initialize(language, description) ⇒ FiniteAutomata
constructor
Initializes a new instance of the FiniteAutomata.
-
#intersection(fa) ⇒ Object
Generates the finite automata for the intersection of two different finite automatas.
- #to_s ⇒ Object
-
#union(fa) ⇒ Object
Generates the finite automata for the union of two different finite automatas.
Constructor Details
#initialize(language, description) ⇒ FiniteAutomata
Initializes a new instance of the FiniteAutomata.
15 16 17 18 19 20 21 |
# File 'lib/fae/finite_automata.rb', line 15 def initialize(language, description) @states = [] @strings = [] @invalids = [] @language = language @description = description end |
Instance Attribute Details
#description ⇒ Object (readonly)
Returns the value of attribute description.
8 9 10 |
# File 'lib/fae/finite_automata.rb', line 8 def description @description end |
#language ⇒ Object (readonly)
Returns the value of attribute language.
8 9 10 |
# File 'lib/fae/finite_automata.rb', line 8 def language @language end |
#states ⇒ Object (readonly)
Returns the value of attribute states.
8 9 10 |
# File 'lib/fae/finite_automata.rb', line 8 def states @states end |
#strings ⇒ Object (readonly)
Returns the value of attribute strings.
8 9 10 |
# File 'lib/fae/finite_automata.rb', line 8 def strings @strings end |
#valid_block ⇒ Object
Returns the value of attribute valid_block.
9 10 11 |
# File 'lib/fae/finite_automata.rb', line 9 def valid_block @valid_block end |
Instance Method Details
#add_state(new_state) ⇒ Object
Adds a single state to the states array.
49 50 51 52 53 54 55 |
# File 'lib/fae/finite_automata.rb', line 49 def add_state(new_state) valid = true @states.each do |state| raise Fae::DuplicateStateException, 'Duplicate state added for Finite Automata' if new_state.name == state.name end @states << new_state end |
#add_states(states) ⇒ Object
Adds strings to check against when evaluating.
41 42 43 44 |
# File 'lib/fae/finite_automata.rb', line 41 def add_states(states) states.each { |state| add_state(state) } self end |
#add_string(string) ⇒ Object
Adds a single string to the strings array.
34 35 36 |
# File 'lib/fae/finite_automata.rb', line 34 def add_string(string) @strings << string end |
#add_strings(strings) ⇒ Object
Adds strings to check against when evaluating.
26 27 28 29 |
# File 'lib/fae/finite_automata.rb', line 26 def add_strings(strings) strings.each { |string| @strings << string } self end |
#difference(fa) ⇒ Object
Generates the finite automata for the difference of two different finite automatas.
94 95 96 |
# File 'lib/fae/finite_automata.rb', line 94 def difference(fa) perform_set_operation(:difference, fa) end |
#evaluate!(suppress_output = false) ⇒ Object
Runs the evaluation on the finite automata.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/fae/finite_automata.rb', line 99 def evaluate!(suppress_output=false) raise Fae::EmptyStatesException, 'You must add some states to your Finite Automata before checking strings' if @states.length == 0 output = "Evaluating strings for #{@description} using language #{@language.characters}".colorize(:yellow) @invalids = [] @strings.each do |string| result = evaluate_string(string) @invalids << string if !result[:valid] output << result[:output] end num_invalid = @invalids.length valid = num_invalid == 0 if !valid output << "\nState diagram may be incorrect for #{@description}\n".colorize(:red) output << "\nA total of #{num_invalid} string#{'s' if num_invalid != 1} did not meet your expectations:\n\n" @invalids.each do |string| expected_string = string.expected ? "valid".colorize(:green) : "invalid".colorize(:red) output << "* You expected the string '#{string.colorize(:blue)}' to be #{expected_string}\n" end output << "\nIf these expectations are correct, then your state diagram needs revising. Otherwise, you've simply expected the wrong values." else output << "\nState diagram is correct.\n".colorize(:green) end if (!suppress_output) puts output end valid end |
#generate_strings(number, length) ⇒ Object
Generates strings for the finite automata and adds them to the strings array.
137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/fae/finite_automata.rb', line 137 def generate_strings(number, length) raise Fae::MissingValidBlockException, 'You must set the valid block for the Finite Automata to generate strings' if valid_block.nil? strings = [] number.times do string = "" length.times { string << @language.characters.sample } strings << String.new(string, valid_block.call(string)) end self.add_strings(strings) self end |
#get_state(name) ⇒ Object
Retrieves a state from this finite automata by name.
60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/fae/finite_automata.rb', line 60 def get_state(name) retrieved_state = nil @states.each do |state| if (state.name == name) retrieved_state = state break end end if (retrieved_state.nil?) raise Fae::StateNotFoundException, "State #{name} was not found in this Finite Automata. Ensure that all states have outputs for #{@language.characters}" end retrieved_state end |
#intersection(fa) ⇒ Object
Generates the finite automata for the intersection of two different finite automatas.
78 79 80 |
# File 'lib/fae/finite_automata.rb', line 78 def intersection(fa) perform_set_operation(:intersection, fa) end |
#to_s ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/fae/finite_automata.rb', line 150 def to_s output = "Description: ".colorize(:yellow) + @description output << "\nLanguage: ".colorize(:yellow) + language.characters.to_s output << "\nStates:".colorize(:yellow) @states.each do |state| output << "\n State #{state.name}: ".colorize(:blue) state.paths.keys.each do |key| output << "\n #{'~'.colorize(:yellow)} #{key} #{'->'.colorize(:light_black)} #{state.paths[key]}" end accepting = state.accepting ? "accepting".colorize(:green) : "not accepting".colorize(:red) output << "\n #{'~'.colorize(:yellow)} #{accepting}" end output end |
#union(fa) ⇒ Object
Generates the finite automata for the union of two different finite automatas.
86 87 88 |
# File 'lib/fae/finite_automata.rb', line 86 def union(fa) perform_set_operation(:union, fa) end |