rlsm 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/Manifest.txt +15 -0
- data/README.txt +68 -0
- data/Rakefile +13 -0
- data/bin/rlsm +0 -0
- data/lib/data/monoids.db +0 -0
- data/lib/rlsm/dfa.rb +696 -0
- data/lib/rlsm/exceptions.rb +39 -0
- data/lib/rlsm/mgen.rb +138 -0
- data/lib/rlsm/monkey_patching.rb +126 -0
- data/lib/rlsm/monoid.rb +544 -0
- data/lib/rlsm/monoid_db.rb +123 -0
- data/lib/rlsm/regexp.rb +593 -0
- data/lib/rlsm.rb +39 -0
- data/test/test_rlsm.rb +0 -0
- metadata +90 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of the RLSM gem.
|
3
|
+
#
|
4
|
+
#(The MIT License)
|
5
|
+
#
|
6
|
+
#Copyright (c) 2008 Gunther Diemant <g.diemant@gmx.net>
|
7
|
+
#
|
8
|
+
#Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
#a copy of this software and associated documentation files (the
|
10
|
+
#'Software'), to deal in the Software without restriction, including
|
11
|
+
#without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
#distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
#permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
#the following conditions:
|
15
|
+
#
|
16
|
+
#The above copyright notice and this permission notice shall be
|
17
|
+
#included in all copies or substantial portions of the Software.
|
18
|
+
#
|
19
|
+
#THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
#MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
#IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
#CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
#TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
25
|
+
#SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
#
|
27
|
+
|
28
|
+
|
29
|
+
class RLSMException < Exception
|
30
|
+
end
|
31
|
+
|
32
|
+
class MonoidException < RLSMException
|
33
|
+
end
|
34
|
+
|
35
|
+
class DFAException < RLSMException
|
36
|
+
end
|
37
|
+
|
38
|
+
class RegExpException < RLSMException
|
39
|
+
end
|
data/lib/rlsm/mgen.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of the RLSM gem.
|
3
|
+
#
|
4
|
+
#(The MIT License)
|
5
|
+
#
|
6
|
+
#Copyright (c) 2008 Gunther Diemant <g.diemant@gmx.net>
|
7
|
+
#
|
8
|
+
#Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
#a copy of this software and associated documentation files (the
|
10
|
+
#'Software'), to deal in the Software without restriction, including
|
11
|
+
#without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
#distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
#permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
#the following conditions:
|
15
|
+
#
|
16
|
+
#The above copyright notice and this permission notice shall be
|
17
|
+
#included in all copies or substantial portions of the Software.
|
18
|
+
#
|
19
|
+
#THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
#MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
#IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
#CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
#TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
25
|
+
#SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
#
|
27
|
+
|
28
|
+
require File.join(File.dirname(__FILE__), 'monoid')
|
29
|
+
|
30
|
+
#Generates all monoids of a given order. May take some time if order is greater than 5.
|
31
|
+
module RLSM
|
32
|
+
class MonoidGenerator
|
33
|
+
|
34
|
+
#Iterates over all monoids of order n.
|
35
|
+
def self.each(n=2)
|
36
|
+
#The pathological cases...
|
37
|
+
if n == 1
|
38
|
+
yield Monoid.new('0')
|
39
|
+
return
|
40
|
+
elsif n == 2
|
41
|
+
yield Monoid.new('01 10')
|
42
|
+
yield Monoid.new('01 11')
|
43
|
+
return
|
44
|
+
end
|
45
|
+
|
46
|
+
@@n = n-1
|
47
|
+
@@t = ([0]*((n-1)*(n-1)))/(n-1)
|
48
|
+
@@t = table_adjoin_one
|
49
|
+
@@i, @@j = n-1, n-1
|
50
|
+
|
51
|
+
@@end_reached = false
|
52
|
+
yield Monoid.new(tab_to_str, :normalize => false) if restrictions_satisfied?
|
53
|
+
succ
|
54
|
+
|
55
|
+
while not @@end_reached
|
56
|
+
yield Monoid.new(tab_to_str, :normalize => false)
|
57
|
+
succ
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def self.succ
|
63
|
+
loop do
|
64
|
+
@@t[@@i][@@j] += 1
|
65
|
+
if @@t[@@i][@@j] > @@n
|
66
|
+
@@t[@@i][@@j] = -1
|
67
|
+
if @@i == 1 and @@j == 1
|
68
|
+
@@end_reached = true
|
69
|
+
break
|
70
|
+
elsif @@j == 1
|
71
|
+
@@j = @@n; @@i -= 1
|
72
|
+
else
|
73
|
+
@@j -= 1
|
74
|
+
end
|
75
|
+
else
|
76
|
+
if restrictions_satisfied? and first?
|
77
|
+
if @@i == @@n and @@j == @@n
|
78
|
+
break
|
79
|
+
elsif @@j == @@n
|
80
|
+
@@j = 1; @@i += 1
|
81
|
+
else
|
82
|
+
@@j += 1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.first?
|
90
|
+
(1..@@n).to_a.permutations.collect{|p| p.unshift 0}.all? do |p|
|
91
|
+
#if a permutation changes some elements before the given position
|
92
|
+
#and the replacement is undefined no answer can be given
|
93
|
+
last = (@@i-1)*(@@n) + @@j -1
|
94
|
+
|
95
|
+
index = (0..last).find do |ind|
|
96
|
+
i,j = (ind / (@@n))+1, (ind % (@@n))+1
|
97
|
+
bij = @@t[p.index(i)][p.index(j)]
|
98
|
+
|
99
|
+
(bij == -1) or @@t[i][j] != p[bij]
|
100
|
+
end
|
101
|
+
|
102
|
+
if index
|
103
|
+
i,j = (index / (@@n))+1, (index % (@@n))+1
|
104
|
+
bij = @@t[p.index(i)][p.index(j)]
|
105
|
+
|
106
|
+
(bij == -1) or (@@t[i][j] < p[@@t[p.index(i)][p.index(j)]])
|
107
|
+
else
|
108
|
+
true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.restrictions_satisfied?
|
114
|
+
#Associativity
|
115
|
+
return false unless (0..@@n).to_a.triples.all? do |a,b,c|
|
116
|
+
if [@@t[a][b],
|
117
|
+
@@t[b][c],
|
118
|
+
@@t[a][@@t[b][c]],
|
119
|
+
@@t[@@t[a][b]][c]].include? -1
|
120
|
+
true
|
121
|
+
else
|
122
|
+
@@t[a][@@t[b][c]] == @@t[@@t[a][b]][c]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
true
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.table_adjoin_one
|
130
|
+
res = [(1..@@n).to_a] + @@t
|
131
|
+
(0..@@n).to_a.zip(res).collect { |i,x| [i]+x }
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.tab_to_str
|
135
|
+
@@t.collect { |r| r.join(@@n >= 10 ? ',' : '') }.join(' ')
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of the RLSM gem.
|
3
|
+
#
|
4
|
+
#(The MIT License)
|
5
|
+
#
|
6
|
+
#Copyright (c) 2008 Gunther Diemant <g.diemant@gmx.net>
|
7
|
+
#
|
8
|
+
#Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
#a copy of this software and associated documentation files (the
|
10
|
+
#'Software'), to deal in the Software without restriction, including
|
11
|
+
#without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
#distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
#permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
#the following conditions:
|
15
|
+
#
|
16
|
+
#The above copyright notice and this permission notice shall be
|
17
|
+
#included in all copies or substantial portions of the Software.
|
18
|
+
#
|
19
|
+
#THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
#MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
#IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
#CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
#TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
25
|
+
#SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
#
|
27
|
+
|
28
|
+
|
29
|
+
class Object
|
30
|
+
#Makes a deep copy. Usful for cloning complexer classes.
|
31
|
+
def deep_copy
|
32
|
+
Marshal.load(Marshal.dump(self))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
class Array
|
38
|
+
def tuples
|
39
|
+
res = []
|
40
|
+
self.each { |a| self.each { |b| res << [a,b] } }
|
41
|
+
|
42
|
+
res
|
43
|
+
end
|
44
|
+
|
45
|
+
def triples
|
46
|
+
res = []
|
47
|
+
tuples.each { |a,b| self.each { |c| res << [a,b,c] } }
|
48
|
+
|
49
|
+
res
|
50
|
+
end
|
51
|
+
|
52
|
+
#Only syntactic sugar. Adds an element unless the element is already in the array.
|
53
|
+
def add?(x)
|
54
|
+
if x
|
55
|
+
unless include? x
|
56
|
+
push(x).sort
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
#Returns the powerset of the array (interpreted as set).
|
64
|
+
def powerset
|
65
|
+
ret = self.inject([[]]) do |acc, x|
|
66
|
+
res = []
|
67
|
+
acc.each { |s| res << s; res << ([x]+s).sort }
|
68
|
+
res
|
69
|
+
end
|
70
|
+
|
71
|
+
ret.sort do |s1,s2|
|
72
|
+
if s1.size == s2.size
|
73
|
+
s1 <=> s2
|
74
|
+
else
|
75
|
+
s1.size <=> s2.size
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
#Returns all proper subsets of the array (the array interpreted as a set).
|
81
|
+
def proper_subsets
|
82
|
+
powerset.select { |s| s.size > 0 and s.size < size }
|
83
|
+
end
|
84
|
+
|
85
|
+
#Returns all permutations of the array.
|
86
|
+
def permutations
|
87
|
+
return [self] if size < 2
|
88
|
+
perm = []
|
89
|
+
each { |e| (self - [e]).permutations.each { |p| perm << ([e] + p) } }
|
90
|
+
perm
|
91
|
+
end
|
92
|
+
|
93
|
+
#Returns the Array divided into subarrays each of length +l+. If The size of the array isn't even divisible by +l+, then the last subarray isn't of size +l+.
|
94
|
+
def /(l)
|
95
|
+
res = []
|
96
|
+
|
97
|
+
each_with_index do |x,i|
|
98
|
+
res << [] if i % l == 0
|
99
|
+
res.last << x
|
100
|
+
end
|
101
|
+
|
102
|
+
res
|
103
|
+
end
|
104
|
+
|
105
|
+
#This is some hack, that in my regexp code, it works for both Strings and Arrays...
|
106
|
+
def each_char(&block)
|
107
|
+
each &block
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class String
|
112
|
+
#Iterates over every character in a string. (Compatibility with 1.9 and convinience)
|
113
|
+
def each_char
|
114
|
+
if block_given?
|
115
|
+
scan(/./m) { |c| yield c }
|
116
|
+
else
|
117
|
+
scan(/./m)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
#This is some hack, that in my regexp code, it works for both Strings and Arrays...
|
122
|
+
def reject(&block)
|
123
|
+
tmp = scan(/./m).reject &block
|
124
|
+
tmp.join
|
125
|
+
end
|
126
|
+
end
|