Class: Fae::FiniteAutomata

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

Constructor Details

#initialize(language, description) ⇒ FiniteAutomata

Initializes a new instance of the FiniteAutomata.



14
15
16
17
18
19
20
# File 'lib/fae/finite_automata.rb', line 14

def initialize(language, description)
  @states = []
  @strings = []
  @invalids = []
  @language = language
  @description = description
end

Instance Attribute Details

#descriptionObject (readonly)

Returns the value of attribute description.



8
9
10
# File 'lib/fae/finite_automata.rb', line 8

def description
  @description
end

#languageObject (readonly)

Returns the value of attribute language.



8
9
10
# File 'lib/fae/finite_automata.rb', line 8

def language
  @language
end

#statesObject (readonly)

Returns the value of attribute states.



8
9
10
# File 'lib/fae/finite_automata.rb', line 8

def states
  @states
end

#stringsObject (readonly)

Returns the value of attribute strings.



8
9
10
# File 'lib/fae/finite_automata.rb', line 8

def strings
  @strings
end

Instance Method Details

#add_states(states) ⇒ Object

Adds strings to check against when evaluating.



41
42
43
44
45
# File 'lib/fae/finite_automata.rb', line 41

def add_states(states)
  states.each do |state|
    add_state(state)
  end
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.



25
26
27
28
29
# File 'lib/fae/finite_automata.rb', line 25

def add_strings(strings)
  strings.each do |string|
    @strings << string
  end
end

#difference(fa) ⇒ Object

Generates the finite automata for the difference of two different finite automatas.



84
85
86
# File 'lib/fae/finite_automata.rb', line 84

def difference(fa)
  perform_set_operation(:difference, fa)
end

#evaluate!Object

Runs the evaluation on the finite automata.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/fae/finite_automata.rb', line 89

def evaluate!
  @invalids = []
  if (@states.length == 0)
    raise "You must add some states to your Finite Automata before checking strings"
  end

  puts """Evaluating strings for #{@description} using language #{@language.characters}".colorize(:yellow)
  @strings.each do |string|
    valid = evaluate_string(string)
    if (!valid)
      @invalids << string
    end
  end

  num_invalid = @invalids.length
  if (num_invalid > 0)
    puts "State diagram may be incorrect for #{@description}".colorize(:red)
    puts "\nA total of #{num_invalid} string#{'s' if num_invalid != 1} did not meet your expectations:\n"

    @invalids.each do |string|
      expected_string = string.expected ? "valid".colorize(:green) : "invalid".colorize(:red)
      puts "* You expected the string '#{string.colorize(:blue)}' to be #{expected_string}"
    end
    puts "\nIf these expectations are correct, then your state diagram needs revising. Otherwise, you've simply expected the wrong values."
  else
    puts "State diagram is correct.".colorize(:green)
  end
  puts
end

#get_state(name) ⇒ Object

Retrieves a state from this finite automata by name.



50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/fae/finite_automata.rb', line 50

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 "State #{name} was not found in this Finite Automata. Ensure that all states have outputs for #{@language.characters}"
  end
  return retrieved_state
end

#intersection(fa) ⇒ Object

Generates the finite automata for the intersection of two different finite automatas.



68
69
70
# File 'lib/fae/finite_automata.rb', line 68

def intersection(fa)
  perform_set_operation(:intersection, fa)
end

#to_sObject



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/fae/finite_automata.rb', line 119

def to_s
  output = ""
  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
  return output
end

#union(fa) ⇒ Object

Generates the finite automata for the union of two different finite automatas.



76
77
78
# File 'lib/fae/finite_automata.rb', line 76

def union(fa)
  perform_set_operation(:union, fa)
end