rlsm 0.4.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,8 +3,16 @@ Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
5
  bin/smon
6
- lib/data/monoids.db
7
- lib/dfa.rb
8
- lib/monoid.rb
9
- lib/re.rb
6
+ data/monoids.db
7
+ lib/database.rb
8
+ lib/monkey_patching/array_ext.rb
10
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 CHANGED
@@ -1,2 +1,39 @@
1
- #! /usr/bin/env ruby
2
- puts "Comming soon"
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
File without changes
@@ -0,0 +1,95 @@
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
@@ -0,0 +1,50 @@
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,7 +1,9 @@
1
1
  $:.unshift File.expand_path(File.dirname(__FILE__))
2
2
 
3
+ require 'monkey_patching/array_ext'
4
+
3
5
  module RLSM
4
- VERSION = '0.4.0'
6
+ VERSION = '1.0.0'
5
7
  end
6
8
 
7
9
  #Setting up the exception classes.
@@ -10,51 +12,6 @@ class MonoidException < RLSMException; end
10
12
  class DFAException < RLSMException; end
11
13
  class REException < RLSMException; end
12
14
 
13
- #--
14
- #Monkey patching the Array class
15
- class Array # :nodoc:
16
- #Returns all permutations of the array.
17
- def permutations
18
- return [self] if size < 2
19
- perm = []
20
- each { |e| (self - [e]).permutations.each { |p| perm << ([e] + p) } }
21
- perm
22
- end
23
-
24
- #Returns the powerset of the array (interpreted as set).
25
- def powerset
26
- ret = self.inject([[]]) do |acc, x|
27
- res = []
28
- acc.each { |s| res << s; res << ([x]+s).sort }
29
- res
30
- end
31
-
32
- ret.sort_lex
33
- end
34
-
35
- #Sorts an array of arrays more or less lexicographical.
36
- def sort_lex
37
- sort { |s1, s2| s1.size == s2.size ? s1 <=> s2 : s1.size <=> s2.size }
38
- end
39
-
40
- #Returns the cartesian product of self and the given arrays
41
- def product(*args)
42
- args.inject(self.map { |x| [x] }) do |res,arr|
43
- new = []
44
- arr.each do |x|
45
- new += res.map { |tup| tup += [x] }
46
- end
47
- new
48
- end
49
- end
50
-
51
- #Returns all unordered pairs.
52
- def unordered_pairs
53
- pairs = []
54
- (0...size-1).each do |i|
55
- pairs |= self[i+1..-1].map { |x| [self[i],x] }
56
- end
57
-
58
- pairs
59
- end
60
- end
15
+ require 'rlsm/monoid'
16
+ require 'rlsm/dfa'
17
+ require 'rlsm/re'
@@ -1,6 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'rlsm'))
2
- require 'monoid'
3
- require "re"
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'rlsm'))
4
2
 
5
3
  =begin rdoc
6
4
  ==Basic theory of deterministic finite automaton (short DFA)
@@ -160,6 +158,16 @@ It is required that all occuring states are in the states array and all transiti
160
158
 
161
159
  attr_reader :alphabet, :states, :initial_state, :finals
162
160
 
161
+ #Returns an Array with 3-tuples as transitions.
162
+ def transitions
163
+ res = []
164
+ @alphabet.each do |letter|
165
+ res |= @transitions[letter].to_a.map { |x| [letter] + x }
166
+ end
167
+
168
+ res
169
+ end
170
+
163
171
  #Returns the number of states.
164
172
  def num_states
165
173
  @states.size
@@ -338,7 +346,7 @@ Minimizes the DFA. Takes as optional parameter a hash with only processed key :+
338
346
 
339
347
  #Returns the transition monoid of the DFA.
340
348
  def transition_monoid
341
- RLSM::Monoid.new get_binary_operation, :rename_elements => true
349
+ RLSM::Monoid.new get_binary_operation, :rename => true
342
350
  end
343
351
 
344
352
  #Returns the transition monoid of the equivalent minimal DFA.
@@ -346,6 +354,16 @@ Minimizes the DFA. Takes as optional parameter a hash with only processed key :+
346
354
  minimize.transition_monoid
347
355
  end
348
356
 
357
+ #Synonym for syntactic_monoid
358
+ def to_monoid
359
+ syntactic_monoid
360
+ end
361
+
362
+ #Returns self.
363
+ def to_dfa
364
+ self
365
+ end
366
+
349
367
  #Returns a RE which represents the same language.
350
368
  def to_re
351
369
  les = []
@@ -360,6 +378,49 @@ Minimizes the DFA. Takes as optional parameter a hash with only processed key :+
360
378
  simplify_les_row(les.pop)[:final]
361
379
  end
362
380
 
381
+ def inspect
382
+ "<#{self.class}: #{@states.join(',')}>"
383
+ end
384
+
385
+ def to_s
386
+ output = []
387
+ output << @states.inject(['']) do |res, state|
388
+ prefix = ''
389
+ prefix += '*' if @finals.include? state
390
+ prefix += '->' if initial_state == state
391
+
392
+ res + [prefix + ' ' + state + ' ']
393
+ end
394
+
395
+ @alphabet.each do |letter|
396
+ column = [' ' + letter + ' ']
397
+ @states.each do |state|
398
+ tmp = self[letter,state]
399
+ if tmp.nil?
400
+ column << ' nil '
401
+ else
402
+ column << ' ' + tmp + ' '
403
+ end
404
+ end
405
+
406
+ output << column.clone
407
+ end
408
+
409
+ #Align output
410
+ output.map! do |col|
411
+ max_length = col.map { |x| x.length }.max
412
+ col.map { |x| ' '*(max_length - x.length) + x }
413
+ end
414
+
415
+ rows = (0..@states.size).map { |i| output.map { |col| col[i] } }
416
+ rows.map! { |row| row.join('|') }
417
+ head = rows.shift
418
+ rows.unshift head.scan(/./).map { |c| c == '|' ? '+' : '-' }.join
419
+ rows.unshift head
420
+
421
+ rows.join("\n")
422
+ end
423
+
363
424
  private
364
425
  def initialize_row_for(state)
365
426
  row = { :state => state.clone }
@@ -1,5 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'rlsm'))
2
- require 'dfa'
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'rlsm'))
3
2
 
4
3
  =begin rdoc
5
4
  =The RLSM::Monoid class
@@ -548,7 +547,7 @@ Returns true if the monoid is aperiodic. (A synonym for h_trivial?)
548
547
  end
549
548
 
550
549
  def inspect # :nodoc:
551
- "<#{self.class} : {#{@elements.join(',')}}; #{to_s}>"
550
+ "<#{self.class}: #{to_s}>"
552
551
  end
553
552
 
554
553
  =begin rdoc
@@ -638,9 +637,22 @@ Also if the monoid is syntactic the set returned by disjunctive subset will be u
638
637
  end
639
638
  end
640
639
 
641
- RLSM::DFA.create(:initial => neutral_element,
642
- :finals => finals,
643
- :transitions => get_transitions)
640
+ dfa = RLSM::DFA.create(:initial => neutral_element,
641
+ :finals => finals,
642
+ :transitions => get_transitions)
643
+ dfa.rename_states
644
+
645
+ dfa
646
+ end
647
+
648
+ #Returns itself.
649
+ def to_monoid
650
+ self
651
+ end
652
+
653
+ #Returns the regexp for the language.
654
+ def to_re
655
+ to_dfa.to_re
644
656
  end
645
657
 
646
658
  private
@@ -1,6 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'rlsm'))
2
- require 'dfa'
3
-
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'rlsm'))
4
2
  require 'enumerator'
5
3
 
6
4
  class RLSM::RE
@@ -11,6 +9,10 @@ class RLSM::RE
11
9
  Lambda = '&'
12
10
  Specials = [LeftBracket, RightBracket, Star, Union, Lambda]
13
11
 
12
+ def to_s
13
+ @pattern
14
+ end
15
+
14
16
  def inspect
15
17
  "<#{self.class}: #@pattern>"
16
18
  end
@@ -86,6 +88,16 @@ class RLSM::RE
86
88
  end
87
89
  end
88
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
+
89
101
  #Returns true if the res are equal
90
102
  def ==(other)
91
103
  return true if @pattern == other.pattern
@@ -158,7 +170,7 @@ class RLSM::RE
158
170
 
159
171
  def recursive_split(child, type)
160
172
  if type_of(child) == type
161
- return self.send "split_#{type}".to_sym, child
173
+ return self.send("split_#{type}".to_sym, child)
162
174
  else
163
175
  return [child]
164
176
  end