rlsm 1.1.0 → 1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +26 -0
- data/README +10 -10
- data/Rakefile +9 -55
- data/data/monoids.db +0 -0
- data/examples/benchmark.rb +14 -0
- data/examples/creating_db.rb +52 -0
- data/examples/creating_lists.rb +185 -0
- data/examples/numbers.rb +41 -0
- data/examples/order8.rb +13 -0
- data/examples/presenting_monoids_in_tex.rb +373 -0
- data/examples/regular_monoids.rb +144 -0
- data/ext/array/array_c_ext.c +21 -12
- data/ext/monoid/monoid_c_ext.c +76 -85
- data/lib/rlsm.rb +1 -1
- data/lib/rlsm/dfa.rb +9 -8
- data/lib/rlsm/helper.rb +12 -6
- data/lib/rlsm/monoid.rb +627 -217
- data/lib/rlsm/regexp.rb +2 -1
- data/lib/rlsm/regexp_parser.rb +2 -1
- data/rlsm.gemspec +26 -0
- data/test/test_dfa.rb +16 -14
- data/test/test_monoid.rb +43 -43
- data/test/test_regexp.rb +2 -2
- metadata +51 -83
- data/ext/binop/binop_c_ext.c +0 -57
- data/ext/binop/extconf.rb +0 -2
- data/lib/rlsm/binary_operation.rb +0 -151
- data/test/test_binop.rb +0 -119
data/ext/binop/binop_c_ext.c
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
#include <ruby.h>
|
2
|
-
|
3
|
-
|
4
|
-
static VALUE
|
5
|
-
non_associative_triple(VALUE self) {
|
6
|
-
VALUE table = rb_iv_get(self, "@table");
|
7
|
-
VALUE max = NUM2INT(rb_iv_get(self, "@order"));
|
8
|
-
VALUE base = rb_iv_get(self, "@elements");
|
9
|
-
|
10
|
-
int i,j,k;
|
11
|
-
for (i=0; i < max; ++i) {
|
12
|
-
for (j=0; j < max; ++j) {
|
13
|
-
for (k=0; k < max; ++k) {
|
14
|
-
int ij,jk, i_jk, ij_k;
|
15
|
-
ij = NUM2INT(RARRAY(table)->ptr[max*i + j]);
|
16
|
-
jk = NUM2INT(RARRAY(table)->ptr[max*j + k]);
|
17
|
-
i_jk = NUM2INT(RARRAY(table)->ptr[max*i + jk]);
|
18
|
-
ij_k = NUM2INT(RARRAY(table)->ptr[max*ij + k]);
|
19
|
-
if (ij_k != i_jk) {
|
20
|
-
return (rb_ary_new3(3,RARRAY(base)->ptr[i],RARRAY(base)->ptr[j],RARRAY(base)->ptr[k]));
|
21
|
-
}
|
22
|
-
}
|
23
|
-
}
|
24
|
-
}
|
25
|
-
|
26
|
-
return (Qnil);
|
27
|
-
}
|
28
|
-
|
29
|
-
static VALUE
|
30
|
-
is_commutative(VALUE self) {
|
31
|
-
VALUE table = rb_iv_get(self, "@table");
|
32
|
-
VALUE max = NUM2INT(rb_iv_get(self, "@order"));
|
33
|
-
|
34
|
-
int i,j;
|
35
|
-
for (i=0; i < max; ++i) {
|
36
|
-
for (j=0; j < max; ++j) {
|
37
|
-
if (NUM2INT(RARRAY(table)->ptr[max*i + j]) != NUM2INT(RARRAY(table)->ptr[max*j + i]))
|
38
|
-
return (Qfalse);
|
39
|
-
}
|
40
|
-
}
|
41
|
-
|
42
|
-
return (Qtrue);
|
43
|
-
}
|
44
|
-
|
45
|
-
#ifdef __cplusplus
|
46
|
-
extern "C" {
|
47
|
-
#endif
|
48
|
-
void Init_binop_cext() {
|
49
|
-
VALUE rlsm = rb_define_module("RLSM");
|
50
|
-
VALUE binop = rb_define_class_under(rlsm, "BinaryOperation", rb_cObject);
|
51
|
-
|
52
|
-
rb_define_private_method(binop, "is_commutative", (VALUE(*)(ANYARGS))is_commutative, 0);
|
53
|
-
rb_define_private_method(binop, "non_associative_triple", (VALUE(*)(ANYARGS))non_associative_triple, 0);
|
54
|
-
}
|
55
|
-
#ifdef __cplusplus
|
56
|
-
}
|
57
|
-
#endif
|
data/ext/binop/extconf.rb
DELETED
@@ -1,151 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'helper')
|
2
|
-
RLSM.require_extension 'binop'
|
3
|
-
|
4
|
-
module RLSM
|
5
|
-
class BinaryOperation
|
6
|
-
class << self; alias original_new new; end
|
7
|
-
=begin rdoc
|
8
|
-
Creates a BinaryOperation from given description and validates the result.
|
9
|
-
Raises a ParseError if validation fails.
|
10
|
-
|
11
|
-
The description is of the form
|
12
|
-
[<elements>:]<table>
|
13
|
-
where the optional <elements> part lists the elements on which the binary
|
14
|
-
operation acts in the order in which they appear in the table part.
|
15
|
-
The elements are seperated by commas. The commas are optional if each
|
16
|
-
element is identified by a single letter. no withespaces are allowed in
|
17
|
-
an element identifier.
|
18
|
-
|
19
|
-
The table part describes the transition table of the binary operation.
|
20
|
-
Rows are seperated by at least one whitespace character and elements in
|
21
|
-
a row are seperated by commas. The commas are optional if each element
|
22
|
-
is identified by a single letter.
|
23
|
-
If commas are used in one row to seperate the elements, one must use
|
24
|
-
commas in each row.
|
25
|
-
|
26
|
-
*Remark*: If the elements part is omitted it is assumed that
|
27
|
-
the elements are appearing in the right order and all elements
|
28
|
-
are appearing. This is the case for a monoid with neutral element
|
29
|
-
in the first row.
|
30
|
-
|
31
|
-
*Examples*
|
32
|
-
012 120 201
|
33
|
-
012:000 000 000
|
34
|
-
x1,x2,x3: x1,x2,x2 x2,x2,x1 x3,x2,x1
|
35
|
-
000 000 000 -> error
|
36
|
-
0,1,2 120 2,1,0 -> error
|
37
|
-
=end
|
38
|
-
def self.new(description)
|
39
|
-
binop = new!(description)
|
40
|
-
validate(binop)
|
41
|
-
|
42
|
-
binop
|
43
|
-
end
|
44
|
-
|
45
|
-
#Like new, but without validation of the input.
|
46
|
-
def self.new!(description)
|
47
|
-
original_new *parse(description)
|
48
|
-
end
|
49
|
-
|
50
|
-
#:call-seq:
|
51
|
-
# original_new(table,elements,mapping) -> BinaryOperation
|
52
|
-
#
|
53
|
-
#Creates a BinaryOperation. The arguments are a table an array with elements
|
54
|
-
#and a mapping.
|
55
|
-
#*Remark*: Use this method only if you know what you're doing. No
|
56
|
-
#validation or argument checking is made. Its primary porpose is to speed up
|
57
|
-
#monoid generation in the RLSM::Monoid.each method.
|
58
|
-
def initialize(table, elements, mapping)
|
59
|
-
@table, @elements, @mapping = table, elements, mapping
|
60
|
-
@order = @mapping.size
|
61
|
-
end
|
62
|
-
|
63
|
-
#Internal representation of the table.
|
64
|
-
attr_reader :table
|
65
|
-
|
66
|
-
#Array with all different elements
|
67
|
-
attr_reader :elements
|
68
|
-
|
69
|
-
#The number of elements.
|
70
|
-
attr_reader :order
|
71
|
-
|
72
|
-
#Maps element names to numbers.
|
73
|
-
attr_reader :mapping
|
74
|
-
|
75
|
-
#Calculate the product of +x+ and +y+.
|
76
|
-
#
|
77
|
-
#If at least one of the given elements is unknown raises an ArgumentError.
|
78
|
-
def [](x, y)
|
79
|
-
if @mapping[x].nil?
|
80
|
-
raise ArgumentError, "Unknown element #{x}"
|
81
|
-
elsif @mapping[y].nil?
|
82
|
-
raise ArgumentError, "Unknown element #{y}"
|
83
|
-
else
|
84
|
-
@elements[@table[@mapping[x]*@order + @mapping[y]]]
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
#Checks if binary operation is associative.
|
89
|
-
def associative?
|
90
|
-
!non_associative_triple
|
91
|
-
end
|
92
|
-
|
93
|
-
#Checks if binary operation is commutative.
|
94
|
-
def commutative?
|
95
|
-
is_commutative
|
96
|
-
end
|
97
|
-
|
98
|
-
#Checks if the binary operation is associative. If not raises an BinOpError.
|
99
|
-
def enforce_associativity
|
100
|
-
nat = non_associative_triple
|
101
|
-
|
102
|
-
unless nat.nil?
|
103
|
-
err_str = "(#{nat[0]}#{nat[0]})#{nat[0]} != #{nat[0]}(#{nat[1]}#{nat[2]})"
|
104
|
-
raise BinOpError, "Associativity required, but #{err_str}."
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
private
|
109
|
-
def self.validate(binop)
|
110
|
-
if binop.table.size == 0
|
111
|
-
raise ArgumentError, "No elements given."
|
112
|
-
end
|
113
|
-
|
114
|
-
if binop.table.size != binop.mapping.size**2
|
115
|
-
raise ParseError, "Either to many elements or wrong table format."
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def self.parse(description)
|
120
|
-
mapping = {}
|
121
|
-
elements = []
|
122
|
-
table = []
|
123
|
-
if description =~ /\s*:\s*/
|
124
|
-
elements = desc2ary(Regexp.last_match.pre_match)
|
125
|
-
elements.each_with_index { |el,i| mapping[el] = i }
|
126
|
-
|
127
|
-
desc2ary(Regexp.last_match.post_match).
|
128
|
-
each { |el| table << mapping[el] }
|
129
|
-
else
|
130
|
-
desc2ary(description).each do |element|
|
131
|
-
if mapping[element].nil?
|
132
|
-
mapping[element] = elements.size
|
133
|
-
elements << element
|
134
|
-
end
|
135
|
-
|
136
|
-
table << mapping[element]
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
[table, elements, mapping]
|
141
|
-
end
|
142
|
-
|
143
|
-
def self.desc2ary(str)
|
144
|
-
if str.include?(',')
|
145
|
-
str.gsub(/^\s+/,'').gsub(/,*\s+,*/,',').split(',')
|
146
|
-
else
|
147
|
-
str.gsub(/\s+/,'').scan(/./)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
data/test/test_binop.rb
DELETED
@@ -1,119 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'shoulda'
|
3
|
-
|
4
|
-
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
5
|
-
|
6
|
-
require 'rlsm/binary_operation'
|
7
|
-
|
8
|
-
class BinaryOperationTest < Test::Unit::TestCase
|
9
|
-
context "BinaryOperation::new" do
|
10
|
-
should "Require argument" do
|
11
|
-
assert_raises ArgumentError do
|
12
|
-
RLSM::BinaryOperation.new
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
should "Parse a valid description with elements" do
|
17
|
-
binop = RLSM::BinaryOperation.new "012:000 000 000"
|
18
|
-
|
19
|
-
assert_equal Hash['0', 0, '1', 1, '2', 2], binop.mapping
|
20
|
-
assert_equal %w(0 1 2), binop.elements
|
21
|
-
assert_equal 3, binop.order
|
22
|
-
assert_equal [0]*9, binop.table
|
23
|
-
end
|
24
|
-
|
25
|
-
should "Ignore whitspaces between element seperators" do
|
26
|
-
binop = RLSM::BinaryOperation.new "0, 1,2:0,0,0 0,0, 0 0, 0,0"
|
27
|
-
|
28
|
-
assert_equal Hash['0', 0, '1', 1, '2', 2], binop.mapping
|
29
|
-
assert_equal %w(0 1 2), binop.elements
|
30
|
-
assert_equal 3, binop.order
|
31
|
-
assert_equal [0]*9, binop.table
|
32
|
-
end
|
33
|
-
|
34
|
-
should "Raise ParseError if some commas are missing" do
|
35
|
-
assert_raises ParseError do
|
36
|
-
RLSM::BinaryOperation.new "012:0,1,2 210 2,2,2"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
should "Parse commas in the elements part, no commas in table part" do
|
41
|
-
binop = RLSM::BinaryOperation.new "0,1,2:000 000 000"
|
42
|
-
|
43
|
-
assert_equal Hash['0', 0, '1', 1, '2', 2], binop.mapping
|
44
|
-
assert_equal %w(0 1 2), binop.elements
|
45
|
-
assert_equal 3, binop.order
|
46
|
-
assert_equal [0]*9, binop.table
|
47
|
-
end
|
48
|
-
|
49
|
-
should "Parse commas in the table part, no commas in elements part" do
|
50
|
-
binop = RLSM::BinaryOperation.new "012:0,0,0 0,0,0 0,0,0"
|
51
|
-
|
52
|
-
assert_equal Hash['0', 0, '1', 1, '2', 2], binop.mapping
|
53
|
-
assert_equal %w(0 1 2), binop.elements
|
54
|
-
assert_equal 3, binop.order
|
55
|
-
assert_equal [0]*9, binop.table
|
56
|
-
end
|
57
|
-
|
58
|
-
should "Raise ParseError if too many elements are given." do
|
59
|
-
assert_raises ParseError do
|
60
|
-
RLSM::BinaryOperation.new "012:0,1,3 210 2,2,2"
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
should "Raise ParseError if too few elements are given." do
|
65
|
-
assert_raises ParseError do
|
66
|
-
RLSM::BinaryOperation.new "000 000 000"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
should "Raise ParseError if table format is wrong." do
|
71
|
-
assert_raises ParseError do
|
72
|
-
RLSM::BinaryOperation.new "012:0,1,2 2,1 2,2,2"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
should "Parse a monoid with neutral element in first row." do
|
77
|
-
binop = RLSM::BinaryOperation.new "0123 1230 2301 3012"
|
78
|
-
|
79
|
-
assert_equal Hash['0', 0, '1', 1, '2', 2, '3', 3], binop.mapping
|
80
|
-
assert_equal %w(0 1 2 3), binop.elements
|
81
|
-
assert_equal 4, binop.order
|
82
|
-
assert_equal [0,1,2,3,1,2,3,0,2,3,0,1,3,0,1,2], binop.table
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
context "BinaryOperation#associative?" do
|
87
|
-
should "Return true if binary operation is associative." do
|
88
|
-
assert_equal true, RLSM::BinaryOperation.new("01:00 00").associative?
|
89
|
-
end
|
90
|
-
|
91
|
-
should "Return false if binary operation is not associative." do
|
92
|
-
assert_equal false, RLSM::BinaryOperation.new("01 00").associative?
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
context "BinaryOperation#commutative?" do
|
97
|
-
should "Return true if binary operation is commutative." do
|
98
|
-
assert_equal true, RLSM::BinaryOperation.new("012 111 211").commutative?
|
99
|
-
end
|
100
|
-
|
101
|
-
should "Return false if binary operation is not commutative." do
|
102
|
-
assert_equal false, RLSM::BinaryOperation.new("012 111 222").commutative?
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
context "BinaryOperation#enforce_associativity" do
|
107
|
-
should "Raise BinOpError for nonassociative binary operation." do
|
108
|
-
assert_raises BinOpError do
|
109
|
-
RLSM::BinaryOperation.new("01 00").enforce_associativity
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
should "Do nothing for assovityive binary operation." do
|
114
|
-
assert_nothing_raised do
|
115
|
-
RLSM::BinaryOperation.new("01 10").enforce_associativity
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|