rlsm 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +0,0 @@
1
- === 1.0.0 / 2008-11-09
2
-
3
- * 1 major enhancement
4
-
5
- * Birthday!
6
-
@@ -1,18 +0,0 @@
1
- History.txt
2
- Manifest.txt
3
- README.txt
4
- Rakefile
5
- bin/smon
6
- data/monoids.db
7
- lib/database.rb
8
- lib/monkey_patching/array_ext.rb
9
- lib/rlsm.rb
10
- lib/rlsm/dfa.rb
11
- lib/rlsm/monoid.rb
12
- lib/rlsm/re.rb
13
- lib/smon/base.rb
14
- lib/smon/db.rb
15
- lib/smon/dot.rb
16
- lib/smon/latex.rb
17
- lib/smon/smon.rb
18
- stdarb.tex
data/bin/smon DELETED
@@ -1,39 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.join(File.dirname(__FILE__), '..', 'lib', 'smon', 'smon')
3
- require 'optparse'
4
-
5
- Version = RLSM::VERSION
6
- out = STDOUT
7
- path = ""
8
-
9
- opts = OptionParser.new do |op|
10
- op.banner = <<USEAGE
11
- Usage: smon [-oh] [FILE1 FILE2 ...]
12
- Executes each FILE as smon script or if no file is given
13
- starts in interactive mode.
14
-
15
- USEAGE
16
- op.separator("Options:")
17
-
18
- op.on('-p','--path PATH', "Adds PATH to the loadpath for librarys.") do |p|
19
- path = p
20
- end
21
-
22
- op.on('-o', '--out FILE', "Output is redirected to FILE.") do |f|
23
- out = File.open(f, 'w')
24
- end
25
-
26
- op.on_tail('-h', '--help', "This help.") { puts op; exit }
27
- op.on_tail('--version', "Shows version.") { puts op.ver }
28
- end
29
-
30
- begin
31
- opts.parse! ARGV
32
-
33
- SMON.new :files =>ARGV, :messenger => out, :path => path
34
- rescue => e
35
- STDERR.puts "Error: #{e.message}"
36
- STDERR.puts
37
- STDERR.puts opts
38
- exit 1
39
- end
Binary file
@@ -1,95 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'rlsm'))
2
-
3
- require "rubygems"
4
- require "sqlite3"
5
-
6
- class RLSM::MonoidDB
7
- @@db = SQLite3::Database.open(File.join(File.dirname(__FILE__), '..',
8
- 'data', 'monoids.db'))
9
-
10
- Columns = [:binop, :m_order, :num_generators,
11
- :num_idempotents, :num_left_nulls, :num_right_nulls,
12
- :syntactic, :idempotent, :aperiodic,
13
- :commutative, :is_group, :has_null,
14
- :l_trivial, :r_trivial, :d_trivial]
15
-
16
- def self.query(query, &block)
17
- if block_given?
18
- @@db.execute(query, &block)
19
- else
20
- @@db.execute(query)
21
- end
22
- end
23
-
24
- def self.find(params = {}, &block)
25
- if block_given?
26
- query construct_query(params), &block
27
- else
28
- query construct_query(params)
29
- end
30
- end
31
-
32
- def self.count(params = {})
33
- q = construct_query(params).sub('T binop F',
34
- "T count(*), total(syntactic) F")
35
- query(q).first.map { |x| x.to_i }
36
- end
37
-
38
- def self.statistic
39
- res = @@db.execute2 <<SQL
40
- SELECT
41
- m_order AS 'Order',
42
- count(*) AS 'Total',
43
- total(syntactic) AS 'Syntactic',
44
- total(is_group) AS 'Groups',
45
- total(commutative) AS 'Commutative',
46
- total(aperiodic) AS 'Aperiodic',
47
- total(idempotent) AS 'Idempotent'
48
- FROM monoids
49
- GROUP BY m_order
50
- ORDER BY 'Order' ASC;
51
- SQL
52
-
53
- desc = res.shift
54
- res.map! { |row| row.map { |x| x.to_i } }
55
- res.unshift desc
56
-
57
- res
58
- end
59
-
60
- private
61
- def self.construct_query(params)
62
- limit = ""
63
- if params[:limit]
64
- limit = "\nLIMIT #{params[:limit]}"
65
- params.delete :limit
66
- if params[:offset]
67
- limit += " OFFSET #{params[:offset]}"
68
- end
69
- end
70
-
71
- order_by = "\nORDER BY binop #{params[:ordering] || 'ASC'}"
72
-
73
- params.delete :ordering
74
-
75
- q = "SELECT binop FROM monoids"
76
-
77
- where = Columns.inject([]) do |res,col|
78
- if params[col]
79
- if [:binop, :m_order].include?(col) or col.to_s =~ /^num_/
80
- res << "#{col.to_s} = #{params[col]}"
81
- else
82
- res << "#{col.to_s} = 1"
83
- end
84
- end
85
-
86
- res
87
- end.join(" AND ")
88
-
89
- if where.length > 0
90
- q += "\nWHERE " + where
91
- end
92
-
93
- q + order_by + limit + ";"
94
- end
95
- end
@@ -1,50 +0,0 @@
1
- module RLSMArrayExt # :nodoc:
2
- #Returns all permutations of the array.
3
- def permutations
4
- return [self] if size < 2
5
- perm = []
6
- each { |e| (self - [e]).permutations.each { |p| perm << ([e] + p) } }
7
- perm
8
- end
9
-
10
- #Returns the powerset of the array (interpreted as set).
11
- def powerset
12
- ret = self.inject([[]]) do |acc, x|
13
- res = []
14
- acc.each { |s| res << s; res << ([x]+s).sort }
15
- res
16
- end
17
-
18
- ret.sort_lex
19
- end
20
-
21
- #Sorts an array of arrays more or less lexicographical.
22
- def sort_lex
23
- sort { |s1, s2| s1.size == s2.size ? s1 <=> s2 : s1.size <=> s2.size }
24
- end
25
-
26
- #Returns the cartesian product of self and the given arrays
27
- def product(*args)
28
- args.inject(self.map { |x| [x] }) do |res,arr|
29
- new = []
30
- arr.each do |x|
31
- new += res.map { |tup| tup += [x] }
32
- end
33
- new
34
- end
35
- end
36
-
37
- #Returns all unordered pairs.
38
- def unordered_pairs
39
- pairs = []
40
- (0...size-1).each do |i|
41
- pairs |= self[i+1..-1].map { |x| [self[i],x] }
42
- end
43
-
44
- pairs
45
- end
46
- end
47
-
48
- class Array # :nodoc:
49
- include RLSMArrayExt
50
- end
@@ -1,504 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'rlsm'))
2
- require 'enumerator'
3
-
4
- class RLSM::RE
5
- LeftBracket = '('
6
- RightBracket = ')'
7
- Star = '*'
8
- Union = '|'
9
- Lambda = '&'
10
- Specials = [LeftBracket, RightBracket, Star, Union, Lambda]
11
-
12
- def to_s
13
- @pattern
14
- end
15
-
16
- def inspect
17
- "<#{self.class}: #@pattern>"
18
- end
19
-
20
- def initialize(pattern = '')
21
- if pattern == ''
22
- @empty_set = true
23
- elsif pattern.scan(/./).all? { |x| Specials.include? x }
24
- @pattern = Lambda
25
- else
26
- @pattern = pattern
27
- end
28
-
29
- unless @empty_set
30
- validate_brackets_balanced
31
- validate_form
32
- preparse
33
- parse
34
- else
35
- @pattern = ''
36
- @parsed = { :first => [], :last => [], :follow => [], :null => false }
37
- end
38
- end
39
-
40
- #Returns the patttern of the regexp
41
- attr_reader :pattern
42
-
43
- #Returns the union of this and the other re as new re.
44
- def +(other)
45
- #One is the empty set?
46
- return RLSM::RE.new(@pattern) if other.pattern == ''
47
- return RLSM::RE.new(other.pattern) if @pattern == ''
48
-
49
- RLSM::RE.new(LeftBracket + @pattern + RightBracket +
50
- Union +
51
- LeftBracket + other.pattern + RightBracket)
52
- end
53
-
54
- #Returns the catenation of this and other re.
55
- def *(other)
56
- #One is the empty set?
57
- return RLSM::RE.new if other.pattern == '' or @pattern == ''
58
-
59
- RLSM::RE.new(LeftBracket + @pattern + RightBracket +
60
- LeftBracket + other.pattern + RightBracket)
61
- end
62
-
63
- #Returns the stared re.
64
- def star
65
- return RLSM::RE.new if @pattern == ''
66
- RLSM::RE.new(LeftBracket + @pattern + RightBracket + Star)
67
- end
68
-
69
- #Alters the re in place to the star form. Returns the altered re.
70
- def star!
71
- unless @pattern == ''
72
- @pattern = LeftBracket + @pattern + RightBracket + Star
73
- parse
74
- end
75
-
76
- self
77
- end
78
-
79
- #Returns a minimal DFA which accepts the same language.
80
- def to_dfa
81
- if @empty_set
82
- RLSM::DFA.new(:alphabet => [],:states => ['0'],:initial => '0',
83
- :finals => [], :transitions => [])
84
- else
85
- add_initial_state
86
- perform_subset_construction
87
- RLSM::DFA.create(@dfa_hash).minimize!(:rename => :new)
88
- end
89
- end
90
-
91
- #Returns the syntactic monoid to this language.
92
- def to_monoid
93
- to_dfa.to_monoid
94
- end
95
-
96
- #Returns self.
97
- def to_re
98
- self
99
- end
100
-
101
- #Returns true if the res are equal
102
- def ==(other)
103
- return true if @pattern == other.pattern
104
-
105
- to_dfa.isomorph_to?(other.to_dfa)
106
- end
107
-
108
- private
109
- def add_initial_state
110
- @parsed[:initial] = [-1]
111
- @parsed[:follow] |= @parsed[:initial].product(@parsed[:first])
112
- end
113
-
114
- def perform_subset_construction
115
- @dfa_hash = {:transitions => [], :finals => [], :initial => '0'}
116
- @dfa_hash[:finals] << @parsed[:initial] if @parsed[:null]
117
- alphabet = @iso.uniq
118
- unmarked = [@parsed[:initial]]
119
- marked = []
120
- until unmarked.empty?
121
- state = unmarked.shift
122
- marked << state
123
- alphabet.each do |char|
124
- nstate = move(state, char)
125
- unmarked << nstate unless (unmarked | marked).include? nstate
126
- if @parsed[:last].any? { |x| nstate.include? x }
127
- @dfa_hash[:finals] << nstate unless @dfa_hash[:finals].include? nstate
128
- end
129
- @dfa_hash[:transitions] << [char, state, nstate]
130
- end
131
- end
132
-
133
- @dfa_hash[:finals].map! { |x| marked.index(x).to_s }
134
- @dfa_hash[:transitions].map! { |c,x,y| [c,marked.index(x).to_s,
135
- marked.index(y).to_s] }
136
- end
137
-
138
- def move(state,c)
139
- state.map do |x|
140
- @parsed[:follow].find_all { |y,z| y == x and @iso[z] == c }.map do |a|
141
- a.last
142
- end
143
- end.flatten.uniq.sort
144
- end
145
-
146
- def parse
147
- pat, @iso = transform_pattern_to_unique_identifiers
148
-
149
- @parsed = parse_pattern(pat)
150
- @pattern = @parsed[:pattern]
151
- end
152
-
153
- def parse_pattern(pat, parent = nil)
154
- pat = remove_surrounding_brackets pat
155
- pat = [Lambda] if pat.all? { |x| Specials.include? x }
156
-
157
- case type_of pat
158
- when :term : return parse_term(pat, parent)
159
- when :star : return parse_star(pat, parent)
160
- when :union : return parse_union(pat, parent)
161
- when :cat : return parse_cat(pat, parent)
162
- else
163
- raise REException, "Unable to parse pattern: #{pat.join}"
164
- end
165
- end
166
-
167
- def parse_children(childs, parent)
168
- childs.map { |child| parse_pattern(child, parent) }
169
- end
170
-
171
- def recursive_split(child, type)
172
- if type_of(child) == type
173
- return self.send("split_#{type}".to_sym, child)
174
- else
175
- return [child]
176
- end
177
- end
178
-
179
- def parse_union(p, parent)
180
- childs = parse_children(split_union(p), parent)
181
- childs = simplify_union(childs, parent)
182
-
183
- #If after simplification there is only one child left, the union isn't
184
- #needed anymore.
185
- return childs.first if childs.size == 1
186
-
187
- childs = sort_union(childs)
188
-
189
- construct_union_result_from childs
190
- end
191
-
192
- def split_union(p)
193
- depth = 0
194
- splitted = [[]]
195
- p.each do |x|
196
- depth += count(x)
197
- if depth == 0 and x == Union
198
- splitted << remove_surrounding_brackets(splitted.pop)
199
- splitted << []
200
- else
201
- splitted.last << x
202
- end
203
- end
204
-
205
- splitted.inject([]) { |res,x| res | recursive_split(x, :union) }
206
- end
207
-
208
- def simplify_union(childs, parent)
209
- #Check if we need an empty word, not the case if
210
- # - parent is a star
211
- # - some nullable choices exists
212
- if childs.any? { |x| x[:null] and x[:pattern] != Lambda } or parent == :star
213
- childs = childs.reject { |x| x[:pattern] == Lambda }
214
- end
215
-
216
- #Simplify somthing like 'a|a' to 'a'
217
- childs.inject([]) do |res,child|
218
- res << child unless res.any? { |x| x[:pattern] == child[:pattern] }
219
- res
220
- end
221
- end
222
-
223
- def sort_union(childs)
224
- childs.sort do |x1,x2|
225
- if x1[:pattern] == Lambda
226
- -1
227
- elsif x2[:pattern] == Lambda
228
- 1
229
- else
230
- x1[:pattern] <=> x2[:pattern]
231
- end
232
- end
233
- end
234
-
235
- def construct_union_result_from(childs)
236
- res = {}
237
- res[:type] = :union
238
-
239
- res[:null] = childs.any? { |x| x[:null] }
240
- res[:first] = childs.map { |x| x[:first] }.flatten
241
- res[:last] = childs.map { |x| x[:last] }.flatten
242
- res[:follow] = childs.inject([]) { |r,x| r | x[:follow] }
243
- res[:pattern] = childs.map { |x| x[:pattern] }.join(Union)
244
-
245
- res
246
- end
247
-
248
- def parse_cat(p, parent)
249
- childs = parse_children(split_cat(p), parent)
250
-
251
- childs = simplify_cat(childs, parent)
252
-
253
- #If after simplification there is only one child left, the cat isn't
254
- #needed anymore.
255
- return childs.first if childs.size == 1
256
-
257
- construct_cat_result_from childs
258
- end
259
-
260
- def split_cat(p)
261
- splitted = [[]]
262
- depth = 0
263
- p.each_with_index do |x,i|
264
- depth += count(x)
265
- if depth == 1 and x == LeftBracket
266
- splitted << [LeftBracket]
267
- elsif depth == 0
268
- if p[i+1] == Star
269
- if x == RightBracket
270
- splitted.last << RightBracket
271
- splitted.last << Star
272
- splitted << []
273
- else
274
- splitted << [x,Star]
275
- splitted << []
276
- end
277
- else
278
- splitted.last << x unless x == Star
279
- if x == RightBracket
280
- last = splitted.pop
281
- splitted << remove_surrounding_brackets(last) unless last.empty?
282
- splitted << []
283
- end
284
- end
285
- else
286
- splitted.last << x
287
- end
288
- end
289
-
290
- splitted.inject([]) do |res,x|
291
- unless x.empty? or x == [Lambda]
292
- res | recursive_split(x, :cat)
293
- else
294
- res
295
- end
296
- end
297
- end
298
-
299
- def simplify_cat(childs, parent)
300
- #Simplify a*a* to a*
301
- childs = childs.inject([]) do |res, child|
302
- unless child[:type] == :star and
303
- res.last and res.last[:type] == :star and
304
- child[:pattern] == res.last[:pattern]
305
- res << child
306
- end
307
-
308
- res
309
- end
310
-
311
- #Simplify (aa*)* to a*
312
- if parent == :star and childs.size == 2
313
- star_exp, other = childs.partition { |x| x[:type] == :star }
314
- unless star_exp.empty? or other.empty?
315
- p1 = remove_surrounding_brackets(star_exp.first[:pattern].
316
- scan(/./)[0..-2])
317
- p2 = remove_surrounding_brackets(other.first[:pattern].
318
- scan(/./))
319
-
320
- if p1 == p2
321
- return other
322
- end
323
- end
324
- end
325
-
326
- childs
327
- end
328
-
329
- def construct_cat_result_from(childs)
330
- childs.map! do |x|
331
- if x[:type] == :union
332
- x[:pattern] = LeftBracket + x[:pattern] + RightBracket
333
- x
334
- else
335
- x
336
- end
337
- end
338
-
339
- res = {}
340
- res[:null] = childs.all? { |x| x[:null] }
341
-
342
- childs.each do |x|
343
- res[:first] = (res[:first] ||= []) | x[:first]
344
- break unless x[:null]
345
- end
346
-
347
- childs.reverse.each do |x|
348
- res[:last] = (res[:last] ||= []) | x[:last]
349
- break unless x[:null]
350
- end
351
-
352
- res[:follow] = childs.inject([]) { |r,x| r | x[:follow] }
353
-
354
- (1...childs.size).each do |i|
355
- res[:follow] |= childs[i-1][:last].product(childs[i][:first])
356
- j = i
357
- while childs[j][:null] and (j < childs.size - 1)
358
- res[:follow] |= childs[i-1][:last].product(childs[j+1][:first])
359
- j += 1
360
- end
361
- end
362
-
363
- res[:pattern] = childs.map { |x| x[:pattern] }.join
364
-
365
- res
366
- end
367
-
368
- def parse_term(pat, parent)
369
- pat = pat.reject { |x| x == Lambda }
370
-
371
- res = {}
372
-
373
- res[:first] = [pat.first].compact
374
- res[:last] = [pat.last].compact
375
- res[:follow] = pat.enum_cons(2).to_a
376
- res[:null] = pat.empty?
377
- res[:pattern] = if res[:null]
378
- Lambda
379
- else
380
- pat.map { |i| @iso[i] }.join
381
- end
382
- res
383
- end
384
-
385
- def parse_star(pat, parent)
386
- pat = remove_surrounding_brackets(pat[0..-2])
387
- child = parse_pattern(pat, :star)
388
-
389
- if child[:pattern] == Lambda or child[:type] == :star
390
- return child
391
- else
392
- res = {}
393
- res[:type] = :star
394
- res[:null] = true
395
- res[:first] = child[:first]
396
- res[:last] = child[:last]
397
- res[:follow] = (child[:follow] | child[:last].product(child[:first]))
398
- res[:pattern] = if child[:pattern].size > 1
399
- LeftBracket + child[:pattern] + RightBracket + Star
400
- else
401
- child[:pattern] + Star
402
- end
403
-
404
- return res
405
- end
406
- end
407
-
408
- def remove_surrounding_brackets(pat)
409
- pat = pat[1..-2] while type_of(pat) == :surr_brackets
410
- pat
411
- end
412
-
413
- def type_of(p)
414
- return :term unless p.any? { |x| (Specials - [Lambda]).include? x }
415
-
416
- unnested_characters = []
417
- depth = 0
418
- p.each do |x|
419
- if x == LeftBracket
420
- unnested_characters << x if depth == 0
421
- depth += 1
422
- elsif x == RightBracket
423
- depth -= 1
424
- unnested_characters << x if depth == 0
425
- else
426
- unnested_characters << x if depth == 0
427
- end
428
- end
429
-
430
- return :union if unnested_characters.include? Union
431
- return :star if p.size == 2 and p.last == Star and !Specials.include? p[0]
432
- return :star if unnested_characters == [LeftBracket, RightBracket, Star]
433
- return :surr_brackets if unnested_characters == [LeftBracket, RightBracket]
434
- :cat
435
- end
436
-
437
- def transform_pattern_to_unique_identifiers
438
- pat = @pattern.scan(/./)
439
- iso = []
440
- for i in (0...pat.size)
441
- next if Specials.include? pat[i]
442
- iso << pat[i]
443
- pat[i] = iso.size - 1
444
- end
445
-
446
- [pat, iso]
447
- end
448
-
449
- def preparse
450
- substitute_empty_brackets
451
- simplify_brackets_around_singeltons
452
- simplify_lambdastar_to_lambda
453
- simplify_implicit_empty_set_unions
454
- squeeze_repeated_specials
455
- end
456
-
457
- def squeeze_repeated_specials
458
- @pattern.squeeze! Star
459
- @pattern.squeeze! Union
460
- @pattern.squeeze! Lambda
461
- end
462
-
463
- def simplify_implicit_empty_set_unions
464
- @pattern.gsub!(LeftBracket + Union, LeftBracket)
465
- @pattern.gsub!(LeftBracket + Star + Union, LeftBracket)
466
- @pattern.gsub!(Union + Star + Union, Union)
467
- end
468
-
469
- def simplify_lambdastar_to_lambda
470
- str = Lambda + Star
471
- @pattern.gsub!(str, Lambda) while @pattern.include? str
472
- end
473
-
474
- def substitute_empty_brackets
475
- @pattern.gsub! LeftBracket + RightBracket, Lambda
476
- end
477
-
478
- def simplify_brackets_around_singeltons
479
- re = Regexp.new("\\#{LeftBracket}(.)\\#{RightBracket}")
480
- @pattern.gsub!(re, '\1') while @pattern =~ re
481
- end
482
-
483
- def validate_form
484
- if @pattern =~ Regexp.new("\\#{LeftBracket}\\#{Star}[^#{Specials.join}]")
485
- raise REException, "Not wellformed. Detected '#{Regexp.last_match(0)}'"
486
- end
487
- end
488
-
489
- def validate_brackets_balanced
490
- unless 0 == @pattern.scan(/./).inject(0) do |res,x|
491
- res += count(x)
492
- break if res < 0
493
- res
494
- end
495
- raise REException, "Unbalanced parentheses in pattern!"
496
- end
497
- end
498
-
499
- def count(x)
500
- return 1 if x == LeftBracket
501
- return -1 if x == RightBracket
502
- 0
503
- end
504
- end