falafel 0.0.1.1 → 0.0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 796b681163a3d9d57b47cadcb95f1d5e2e9af1e97a0b841b2e31ddc9c725769b
4
- data.tar.gz: 3811e2bc49acfee5aa9a4e4f27569df022fb68c2ddafbafa10b43a7c92afe4d8
3
+ metadata.gz: 5180f16b8868a35cf65faa396c7b341166604e2aaf7db8d9f7099c819630497f
4
+ data.tar.gz: 7c773f6a53d8895333d37115cba598dcf60128bff2eaf4dc47e73f7e1ca21298
5
5
  SHA512:
6
- metadata.gz: 96bf15557a50f7a81c8a71d200a0876f7fc445d64d017d3c2011fa088457d61e05327e8ea39c7147d349049a8e8b3811a815c92e04f414109c4505782a8c6613
7
- data.tar.gz: 45573ad63969221aed699f9412d45409c4f72a26c1ec3e83e3bcb4c5fba03c6fb9bdae80d61b3c0a046e4c25a66a00e7c64c00a1841142de675e7eaa45158876
6
+ metadata.gz: 0b7470e125d1f803eacc1d207704b90782e439fef8c7fe00dcf0acdb6c27324d24ed2da0666b3c456fe7cc7b255902002f20870e8f93d589482d4d1df3370aca
7
+ data.tar.gz: c8534f9da1cfec2623caa5cf0422f3d03009579374d2183a10341398a93aad87fbf2a0e85aaba0a0a766ee1d8ae62baa02e39bd2a76c7857fa6613629ae64f5a
data/lib/cfg.rb CHANGED
@@ -10,7 +10,7 @@ require_relative 'chaining_free'
10
10
  # generates random words
11
11
  class CFG
12
12
  attr_accessor :start_var, :rules
13
- attr_reader :rules_ef, :rules_cf, :rnd_words, :reachables,
13
+ attr_reader :rules_ef, :rules_cf, :rnd_words,
14
14
  :rules_ef_res, :rules_cf_res, :chomsky_nf_rules,
15
15
  :cyk_matrix, :is_in_l
16
16
 
@@ -18,7 +18,6 @@ class CFG
18
18
  @start_var = start_var
19
19
  @rules = _rules rules
20
20
  @rnd_words = []
21
- @reachables = []
22
21
  @vars = vars
23
22
  @alphabet = alphabet
24
23
  end
@@ -35,24 +34,9 @@ class CFG
35
34
  end
36
35
  end
37
36
 
38
- def var_reachable?
39
- @rules[@start_var].each do |rule|
40
- @vars.each { |var| @reachables << var if rule.include? var }
41
- end
42
- @reachables.uniq!
43
- end
44
-
45
- def var_productive?
46
- ''
47
- end
48
-
49
- def var_reduced?
50
- ''
51
- end
52
-
53
- def epsilon_free
37
+ def epsilon_free(custom_rule)
54
38
  e_free = EpsilonFree.new
55
- @rules_ef_res = e_free.run @rules
39
+ @rules_ef_res = e_free.run custom_rule || @rules
56
40
  @rules_ef = e_free.rebuild_rules @rules, @rules_ef_res
57
41
  end
58
42
 
data/lib/chomsky_nf.rb CHANGED
@@ -46,15 +46,15 @@ class ChomskyNF
46
46
  end
47
47
 
48
48
  def _handle_all_rule(new_rules)
49
- new_rules_buffer = {}
49
+ new_rules_buffer = []
50
50
 
51
51
  new_rules.each do |var, rules|
52
52
  next if _is_character? rules
53
53
 
54
- new_rules_buffer = _new_rules_buffer rules, var
54
+ new_rules_buffer << _new_rules_buffer(rules, var)
55
55
  end
56
56
 
57
- new_rules.merge! new_rules_buffer
57
+ new_rules.merge! new_rules_buffer.reduce(&:merge)
58
58
  end
59
59
 
60
60
  def _is_character?(value)
@@ -3,15 +3,15 @@
3
3
  # simplify chomsky normal form
4
4
  class ChomskyNFSimplifier
5
5
  def run(new_rules, alphabet)
6
- var_has_one_letter = _var_has_one_letter new_rules, alphabet
6
+ vars_with_one_letter = _vars_with_one_letter new_rules, alphabet
7
7
 
8
- return new_rules if var_has_one_letter.empty?
8
+ return new_rules if vars_with_one_letter.empty?
9
9
 
10
- rules = _find_modify_rules new_rules, var_has_one_letter
10
+ extendible_rules = _find_extendible_rules new_rules, vars_with_one_letter.keys
11
11
 
12
- return new_rules if rules.empty?
12
+ return new_rules if extendible_rules.empty?
13
13
 
14
- missing_rules = _generate_missing_rules rules, var_has_one_letter
14
+ missing_rules = _missing_rules extendible_rules, vars_with_one_letter
15
15
 
16
16
  _add_missing_rules missing_rules, new_rules
17
17
 
@@ -20,56 +20,57 @@ class ChomskyNFSimplifier
20
20
 
21
21
  private
22
22
 
23
- def _var_has_one_letter(new_rules, alphabet)
23
+ def _vars_with_one_letter(new_rules, alphabet)
24
24
  vars = {}
25
25
 
26
26
  new_rules.each do |key, values|
27
+ # skip simple rules like (A, a), (B, b),...
27
28
  next if values.size == 1
28
29
 
29
- values.each do |val|
30
- next unless val.size == 1 && alphabet.include?(val.downcase)
31
-
32
- vars[key] ||= []
33
- vars[key] << val
34
- end
30
+ letters = values.select { |val| _is_letter val, alphabet }.uniq
31
+ vars[key] = letters
35
32
  end
36
33
 
37
34
  vars
38
35
  end
39
36
 
40
- def _find_modify_rules(new_rules, vars)
41
- modify = {}
37
+ def _is_letter(val, alphabet)
38
+ val.size == 1 && alphabet.include?(val.downcase)
39
+ end
42
40
 
43
- new_rules.each do |key, val|
44
- next if val.is_a?(String)
41
+ def _find_extendible_rules(new_rules, rules_keys)
42
+ extendible = {}
45
43
 
46
- val.each do |v|
47
- vars.each_key do |k|
48
- next unless v.include?(k)
44
+ filterd_rules = new_rules.reject { |_, rules| rules.is_a?(String) }
49
45
 
50
- res = val.select { |x| x.include? k }
46
+ filterd_rules.each do |letter, rules|
47
+ rules_keys.each do |rules_key|
48
+ rules.each do |rule|
49
+ next unless rule.include?(rules_key)
51
50
 
52
- modify[key] ||= []
53
- modify[key] << res
51
+ extendible[letter] ||= []
52
+ extendible[letter] << rule
54
53
  end
55
54
  end
56
55
  end
57
56
 
58
- modify
57
+ extendible
59
58
  end
60
59
 
61
- def _generate_missing_rules(rules, vars)
60
+ def _missing_rules(extendible_rules, vars)
62
61
  res = {}
63
62
 
64
- rules.each do |var_rule, nfs|
65
- nfs.flatten.each do |nf|
63
+ extendible_rules.each do |var_rule, nfs|
64
+ nfs.each do |nf|
66
65
  vars.each do |match_char, replacement_chars|
67
66
  replacement_chars.each do |rc|
68
- new_rules = _combinations nf, rc, match_char
69
67
  res[var_rule] ||= []
70
- res[var_rule] << new_rules
68
+ res[var_rule] << _combinations(nf, rc, match_char)
71
69
  end
72
70
  end
71
+
72
+ res[var_rule] = res[var_rule]&.flatten&.uniq
73
+
73
74
  _check_special_case nf, res, var_rule, vars
74
75
  end
75
76
  end
@@ -93,7 +94,11 @@ class ChomskyNFSimplifier
93
94
  end
94
95
 
95
96
  def _add_missing_rules(missing_rules, new_rules)
96
- missing_rules.each { |key, val| new_rules[key] = val.flatten.uniq! }
97
+ missing_rules.each do |key, val|
98
+ next if val.nil?
99
+
100
+ new_rules[key].concat(val).uniq!
101
+ end
97
102
  end
98
103
 
99
104
  def _check_special_case(nf, res, var_rule, vars)
@@ -102,7 +107,7 @@ class ChomskyNFSimplifier
102
107
 
103
108
  missing_rules = combi.map { |lft| combi.map { |rgt| "#{lft}#{rgt}" } }.flatten
104
109
 
105
- res[var_rule] << missing_rules
110
+ res[var_rule].concat(missing_rules)
106
111
  end
107
112
 
108
113
  res
data/lib/cyk.rb CHANGED
@@ -13,7 +13,7 @@ class CYK
13
13
  def run
14
14
  _cyk_fill_diagonal
15
15
  _cyk_fill_matrix
16
- _is_in_l?
16
+ @is_in_l = _is_in_l?
17
17
  end
18
18
 
19
19
  private
@@ -34,9 +34,9 @@ class CYK
34
34
 
35
35
  next if i == j
36
36
 
37
- helper_var = _helper_var i, j
38
-
39
- @matrix[i][j] = _add_to_matrix helper_var
37
+ helper_var = _helper_var i, j
38
+ matrix_ele_info = _matrix_ele_info i, j
39
+ @matrix[i][j] = _add_to_matrix helper_var, matrix_ele_info
40
40
  end
41
41
  end
42
42
  end
@@ -55,20 +55,44 @@ class CYK
55
55
  res
56
56
  end
57
57
 
58
- def _add_to_matrix(rule)
59
- res = '0'
60
- return if rule == res
58
+ def _matrix_ele_info(i, j)
59
+ res = {}
60
+
61
+ res['i'] = i
62
+ res['j'] = j
63
+ res['row_c'] = @matrix.count
64
+
65
+ res
66
+ end
67
+
68
+ def _add_to_matrix(helper_var, matrix_ele_info)
69
+ matrix_ele = '0'
70
+ return if helper_var == matrix_ele
71
+
72
+ keys = []
61
73
 
62
74
  @rules.each do |key, vals|
63
75
  vals.each do |val|
64
- res = key if val == rule
76
+ keys << key if val == helper_var
65
77
  end
66
78
  end
67
79
 
68
- res
80
+ _matrix_ele keys, matrix_ele_info
81
+ end
82
+
83
+ def _matrix_ele(keys, matrix_ele_info)
84
+ return 'S' if keys.include?('S') && _is_last_element?(matrix_ele_info)
85
+
86
+ return keys.last if keys.size == 1
87
+
88
+ keys.reject { |key| key == 'S' }.last || '0'
89
+ end
90
+
91
+ def _is_last_element?(matrix_ele_info)
92
+ matrix_ele_info['i'].zero? && matrix_ele_info['j'] == matrix_ele_info['row_c'] - 1
69
93
  end
70
94
 
71
95
  def _is_in_l?
72
- @is_in_l = @matrix.first.last == 'S'
96
+ @matrix.first.last == 'S'
73
97
  end
74
98
  end
data/lib/epsilon_free.rb CHANGED
@@ -61,7 +61,7 @@ class EpsilonFree
61
61
  res << epsilon_free_word.delete(e_class) if possibilities.size == 1
62
62
  end
63
63
 
64
- res
64
+ res.uniq.reject(&:nil?)
65
65
  end
66
66
 
67
67
  def _new_rules_epsilon_location(s_rule, e_class)
data/lib/falafel.rb CHANGED
@@ -104,10 +104,10 @@ class Falafel
104
104
  dfa.to_min
105
105
  end
106
106
 
107
- def pump_lemma
107
+ def pump_lemma(lang, length)
108
108
  require_relative 'pump'
109
109
 
110
- Pump.new lang: nil, word: nil, n: 2, k: 20
110
+ Pump.new lang: lang, length: length
111
111
  end
112
112
 
113
113
  def cfg(alphabet, vars_set, start_var, rules)
@@ -118,7 +118,6 @@ class Falafel
118
118
 
119
119
  private
120
120
 
121
- # alle bilder eine menge m unter r
122
121
  def _image(m, r)
123
122
  m.flat_map { |x| r.map { |y, z| z if x == y }.compact }.sort.uniq
124
123
  end
data/lib/pump.rb CHANGED
@@ -2,29 +2,68 @@
2
2
 
3
3
  # Pump Lemma
4
4
  # It takes language as lambda function and a word as a string
5
- # n is the length of the string you want to pump
6
- # k is the potens of the middle word
5
+ # lang is a regular expression like a^*b^* given as lambda function and set by user
6
+ # word is the word to check pumping
7
+ # length is the length of the string you want to pump
8
+ # return is_regular to tell if lang is regular and decomposition to show why
7
9
  class Pump
8
10
  attr_accessor :lang, :word
11
+ attr_reader :is_regular, :decomposition
9
12
 
10
- def initialize(lang:, word:, n:, k:)
11
- @lang = lang
12
- @word = word
13
- @n = n
14
- @k = k
13
+ def initialize(lang:, length:)
14
+ @lang = lang
15
+ @length = length
16
+ @word = ''
15
17
  end
16
18
 
17
- def run
19
+ def run(show_pros:)
20
+ _clear_old_run
21
+
18
22
  r, s, t = ''
19
23
 
20
- (0...@word.length - @n + 1).each do |i|
21
- r = @word[0...i]
22
- s = @word[i...i + @n]
23
- t = @word[i + @n..]
24
+ @word.length.times do |leng|
25
+ r, s, t = _sigma_chars leng
26
+
27
+ pump_up_down_res = _pump_up_down_res r, s, t, show_pros
28
+ not_in_language = pump_up_down_res.include? false
24
29
 
25
- break if s.length.positive? && (r + s * @k + t) != @word && @lang.call(r + s * @k + t)
30
+ @is_regular = false if not_in_language
31
+
32
+ break if not_in_language
26
33
  end
27
34
 
35
+ @decomposition = [r, s, t]
36
+ end
37
+
38
+ private
39
+
40
+ def _clear_old_run
41
+ @decomposition = []
42
+ @is_regular = true
43
+ end
44
+
45
+ # ∃r, s, t ∈ Σ^∗
46
+ def _sigma_chars(leng)
47
+ r = @word[0...leng] || ''
48
+ s = @word[leng...leng + @length] || ''
49
+ t = @word[leng + @length..] || ''
50
+
28
51
  [r, s, t]
29
52
  end
53
+
54
+ # ∀k ≥ 0 : r·s^k·t ∈ L
55
+ def _pump_up_down_res(r, s, t, show_pros)
56
+ pump_up_down_res = []
57
+
58
+ 20.times do |k|
59
+ puts "r: #{r}, s: #{s}, t: #{t}, k: #{k}, r + s * k + t: #{r + s * k + t}" if show_pros
60
+ pump_up_down_res << _pump_condtion_satisfied?(r, s, t, k)
61
+ end
62
+
63
+ pump_up_down_res
64
+ end
65
+
66
+ def _pump_condtion_satisfied?(r, s, t, k)
67
+ (s.length.positive? && @lang.call(r + s * k + t))
68
+ end
30
69
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: falafel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.1
4
+ version: 0.0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abed Alkedda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-03 00:00:00.000000000 Z
11
+ date: 2023-08-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -28,7 +28,7 @@ files:
28
28
  - lib/rx.rb
29
29
  homepage: https://github.com/AbedAlkedda/AFS
30
30
  licenses:
31
- - Ruby
31
+ - ''
32
32
  metadata: {}
33
33
  post_install_message:
34
34
  rdoc_options: []
@@ -48,5 +48,6 @@ requirements: []
48
48
  rubygems_version: 3.3.26
49
49
  signing_key:
50
50
  specification_version: 4
51
- summary: Falafel is a gem to help you understand Automata better, hopefully
51
+ summary: Falafel is a gem that will hopefully help you better understand automata
52
+ and formal languages
52
53
  test_files: []