rlsm 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Manifest.txt +12 -4
- data/bin/smon +39 -2
- data/{lib/data → data}/monoids.db +0 -0
- data/lib/database.rb +95 -0
- data/lib/monkey_patching/array_ext.rb +50 -0
- data/lib/rlsm.rb +6 -49
- data/lib/{dfa.rb → rlsm/dfa.rb} +65 -4
- data/lib/{monoid.rb → rlsm/monoid.rb} +18 -6
- data/lib/{re.rb → rlsm/re.rb} +16 -4
- data/lib/smon/base.rb +284 -0
- data/lib/smon/db.rb +98 -0
- data/lib/smon/dot.rb +65 -0
- data/lib/smon/latex.rb +313 -0
- data/lib/smon/smon.rb +183 -0
- data/stdarb.tex +118 -0
- metadata +14 -6
data/Manifest.txt
CHANGED
@@ -3,8 +3,16 @@ Manifest.txt
|
|
3
3
|
README.txt
|
4
4
|
Rakefile
|
5
5
|
bin/smon
|
6
|
-
|
7
|
-
lib/
|
8
|
-
lib/
|
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
|
-
|
2
|
-
|
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
|
data/lib/database.rb
ADDED
@@ -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
|
data/lib/rlsm.rb
CHANGED
@@ -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.
|
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
|
-
|
15
|
-
|
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'
|
data/lib/{dfa.rb → rlsm/dfa.rb}
RENAMED
@@ -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, :
|
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}
|
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
|
-
|
643
|
-
|
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
|
data/lib/{re.rb → rlsm/re.rb}
RENAMED
@@ -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
|
173
|
+
return self.send("split_#{type}".to_sym, child)
|
162
174
|
else
|
163
175
|
return [child]
|
164
176
|
end
|