gecoder 0.2.0 → 0.3.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/CHANGES +21 -0
- data/README +9 -1
- data/ext/missing.cpp +1 -1
- data/ext/vararray.cpp +4 -0
- data/ext/vararray.h +2 -1
- data/lib/gecoder/bindings/bindings.rb +55 -5
- data/lib/gecoder/interface.rb +1 -0
- data/lib/gecoder/interface/binding_changes.rb +183 -81
- data/lib/gecoder/interface/branch.rb +1 -1
- data/lib/gecoder/interface/constraints.rb +121 -5
- data/lib/gecoder/interface/constraints/bool/boolean.rb +160 -0
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +23 -0
- data/lib/gecoder/interface/constraints/int/linear.rb +258 -0
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +66 -0
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +31 -0
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +22 -0
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +57 -0
- data/lib/gecoder/interface/enum_wrapper.rb +39 -33
- data/lib/gecoder/interface/model.rb +44 -64
- data/lib/gecoder/interface/search.rb +40 -3
- data/lib/gecoder/interface/variables.rb +62 -0
- metadata +19 -8
- data/lib/gecoder/interface/constraints/distinct.rb +0 -15
- data/lib/gecoder/interface/constraints/linear.rb +0 -158
- data/lib/gecoder/interface/constraints/relation.rb +0 -76
data/CHANGES
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
== Version 0.3.0
|
2
|
+
|
3
|
+
* The constructor of Gecode::Model no longer has to be called by classes inheriting from it.
|
4
|
+
* Added Model#reset! which resets a model after search.
|
5
|
+
* Added Model#solution which passes the first solution to a block and returns the result of that block.
|
6
|
+
* Added Model#each_soltion which iterates over each solution.
|
7
|
+
* Added boolean variables. They are created using Model#bool_var and Model#bool_var_array .
|
8
|
+
* Added two options to constraints: propagation strength and reification variable.
|
9
|
+
* Linear and simple relation constraints can now also be specified using #equal, #equal_to, #greater, #greater_than,... in addition to comparison operators.
|
10
|
+
* Added distinct with offsets.
|
11
|
+
* Simple relation constraints can now be used to specify relations between two variables.
|
12
|
+
* Added basic boolean domain constraints along with conjunction and disjunction.
|
13
|
+
* Added syntactic sugar for combining reifiable constraints with | and &.
|
14
|
+
|
15
|
+
== Version 0.2.0
|
16
|
+
|
17
|
+
This is the first release of Gecode/R, a Ruby interface to Gecode.
|
18
|
+
|
19
|
+
* Added support for finite domain integers.
|
20
|
+
* Added some basic relation, linear and distinct constraints.
|
21
|
+
* Added the basis needed to model problems and find the first solution.
|
data/README
CHANGED
@@ -3,6 +3,14 @@
|
|
3
3
|
Gecode/R is a Ruby interface to Gecode, an open, free and efficient environment
|
4
4
|
for developing constraint-based systems and applications.
|
5
5
|
|
6
|
+
== Warning
|
7
|
+
|
8
|
+
Gecode/R is still in an early development stage, the syntax is by no means
|
9
|
+
final and backwards compatibility will be broken time and time again until
|
10
|
+
later in the development process. Don’t use Gecode/R in production-code yet,
|
11
|
+
it’s merely available this early to allow people to play with it and give
|
12
|
+
feedback.
|
13
|
+
|
6
14
|
== Installation
|
7
15
|
|
8
16
|
Gecode/R requires Gecode 1.3.1, which can be downloaded from
|
@@ -17,4 +25,4 @@ instructions.
|
|
17
25
|
=== Building the gem
|
18
26
|
|
19
27
|
rake gem
|
20
|
-
gem install pkg/gecoder-0.x.gem
|
28
|
+
gem install pkg/gecoder-0.x.x.gem
|
data/ext/missing.cpp
CHANGED
@@ -152,7 +152,7 @@ MSpace::MSpace(MSpace& s, bool share) : Gecode::Space(share, s), d(new Private)
|
|
152
152
|
|
153
153
|
for(it = s.d->boolArrays.begin(); it != eend; it++)
|
154
154
|
{
|
155
|
-
Gecode::MBoolVarArray *bva = new Gecode::MBoolVarArray;
|
155
|
+
Gecode::MBoolVarArray *bva = new Gecode::MBoolVarArray(this, (*it).second->ptr()->size());
|
156
156
|
|
157
157
|
bva->ptr()->update(this, share, *(*it).second->ptr() );
|
158
158
|
|
data/ext/vararray.cpp
CHANGED
@@ -164,6 +164,10 @@ MBoolVarArray::MBoolVarArray(const Gecode::BoolVarArray &arr) : d(new Private)
|
|
164
164
|
setSize(arr.size());
|
165
165
|
setCount(0);
|
166
166
|
}
|
167
|
+
MBoolVarArray::MBoolVarArray (Space *home, int n) : d(new Private)
|
168
|
+
{
|
169
|
+
setArray(Gecode::BoolVarArray(home, n));
|
170
|
+
}
|
167
171
|
|
168
172
|
MBoolVarArray::~MBoolVarArray()
|
169
173
|
{
|
data/ext/vararray.h
CHANGED
@@ -188,6 +188,11 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
188
188
|
ns.add_cxx_class "MBoolVarArray" do |klass|
|
189
189
|
klass.bindname = "BoolVarArray"
|
190
190
|
klass.add_constructor
|
191
|
+
klass.add_constructor do |func|
|
192
|
+
func.add_parameter "Gecode::MSpace *", "home"
|
193
|
+
func.add_parameter "int", "n"
|
194
|
+
end
|
195
|
+
|
191
196
|
klass.add_method "at", "Gecode::BoolVar&" do |method|
|
192
197
|
method.add_parameter "int", "index"
|
193
198
|
end
|
@@ -195,6 +200,11 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
195
200
|
klass.add_operator "[]", "Gecode::BoolVar&" do |method|
|
196
201
|
method.add_parameter "int", "index"
|
197
202
|
end
|
203
|
+
|
204
|
+
klass.add_operator "[]=", "Gecode::BoolVar&" do |method|
|
205
|
+
method.add_parameter "int", "index"
|
206
|
+
method.add_parameter "Gecode::BoolVar", "val"
|
207
|
+
end
|
198
208
|
|
199
209
|
klass.add_method "size", "int"
|
200
210
|
|
@@ -428,6 +438,22 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
428
438
|
klass.add_constructor do |method|
|
429
439
|
method.add_parameter "Gecode::IntVar", "x"
|
430
440
|
end
|
441
|
+
|
442
|
+
klass.add_method "max", "int"
|
443
|
+
|
444
|
+
klass.add_method "min", "int"
|
445
|
+
klass.add_method "med", "int"
|
446
|
+
klass.add_method "val", "int"
|
447
|
+
klass.add_method "size", "unsigned int"
|
448
|
+
klass.add_method "width", "unsigned int"
|
449
|
+
klass.add_method "degree", "unsigned int"
|
450
|
+
|
451
|
+
klass.add_method "range", "bool"
|
452
|
+
klass.add_method "assigned", "bool"
|
453
|
+
klass.add_method "in", "bool" do |method|
|
454
|
+
method.add_parameter "int", "n"
|
455
|
+
end
|
456
|
+
|
431
457
|
klass.add_method "update", "void" do |method|
|
432
458
|
method.add_parameter "Gecode::MSpace*", "home"
|
433
459
|
method.add_parameter "bool", "share"
|
@@ -545,6 +571,12 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
545
571
|
method.add_parameter "Gecode::IntRelType", "irt"
|
546
572
|
method.add_parameter "Gecode::IntConLevel", "icl"
|
547
573
|
end
|
574
|
+
|
575
|
+
klass.add_method "post" do |method|
|
576
|
+
method.add_parameter "Gecode::MSpace *", "home"
|
577
|
+
method.add_parameter "Gecode::IntRelType", "irt"
|
578
|
+
method.add_parameter "Gecode::BoolVar", "b"
|
579
|
+
end
|
548
580
|
|
549
581
|
klass.add_operator "+", "Gecode::MiniModel::LinExpr" do |operator|
|
550
582
|
operator.add_parameter("Gecode::MiniModel::LinExpr", "exp")
|
@@ -597,17 +629,17 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
597
629
|
klass.add_constructor do |method|
|
598
630
|
method.add_parameter "Gecode::MiniModel::BoolExpr", "e"
|
599
631
|
end
|
600
|
-
|
632
|
+
|
633
|
+
klass.add_constructor do |method|
|
634
|
+
method.add_parameter "Gecode::BoolVar", "e"
|
635
|
+
end
|
636
|
+
|
601
637
|
klass.add_constructor do |method|
|
602
638
|
method.add_parameter "Gecode::MiniModel::BoolExpr", "l"
|
603
639
|
method.add_parameter "Gecode::MiniModel::BoolExpr::NodeType", "t"
|
604
640
|
method.add_parameter "Gecode::MiniModel::BoolExpr", "r"
|
605
641
|
end
|
606
642
|
|
607
|
-
klass.add_constructor do |method|
|
608
|
-
method.add_parameter "Gecode::BoolVar", "e"
|
609
|
-
end
|
610
|
-
|
611
643
|
klass.add_constructor do |method|
|
612
644
|
method.add_parameter "Gecode::MiniModel::BoolExpr", "l"
|
613
645
|
method.add_parameter "Gecode::MiniModel::BoolExpr::NodeType", "t"
|
@@ -616,6 +648,15 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
616
648
|
klass.add_constructor do |method|
|
617
649
|
method.add_parameter "Gecode::MiniModel::LinRel", "e"
|
618
650
|
end
|
651
|
+
|
652
|
+
klass.add_method "post" do |method|
|
653
|
+
method.add_parameter "Gecode::MSpace *", "home"
|
654
|
+
end
|
655
|
+
|
656
|
+
klass.add_method "post" do |method|
|
657
|
+
method.add_parameter "Gecode::MSpace *", "home"
|
658
|
+
method.add_parameter "bool", "t"
|
659
|
+
end
|
619
660
|
end
|
620
661
|
|
621
662
|
minimodelns.add_cxx_class "BoolRel" do |klass|
|
@@ -857,6 +898,15 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
857
898
|
func.add_parameter "Gecode::BvarSel", "vars"
|
858
899
|
func.add_parameter "Gecode::BvalSel", "vals"
|
859
900
|
end
|
901
|
+
|
902
|
+
ns.add_function "branch" do |func|
|
903
|
+
func.add_parameter "Gecode::MSpace *", "home"
|
904
|
+
func.add_parameter "Gecode::MBoolVarArray *", "iva" do |param|
|
905
|
+
param.custom_conversion = "*ruby2Gecode_MBoolVarArrayPtr(argv[1], 2)->ptr()"
|
906
|
+
end
|
907
|
+
func.add_parameter "Gecode::BvarSel", "vars"
|
908
|
+
func.add_parameter "Gecode::BvalSel", "vals"
|
909
|
+
end
|
860
910
|
|
861
911
|
ns.add_function "branch" do |func|
|
862
912
|
func.add_parameter "Gecode::MSpace *", "home"
|
data/lib/gecoder/interface.rb
CHANGED
@@ -6,106 +6,208 @@
|
|
6
6
|
#
|
7
7
|
# This layer should be moved to the C++ side instead when possible for better
|
8
8
|
# performance.
|
9
|
-
module Gecode
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
module Gecode
|
10
|
+
module Raw
|
11
|
+
class Space
|
12
|
+
# Creates the specified number of integer variables in the space. Returns
|
13
|
+
# the indices with which they can then be accessed using int_var.
|
14
|
+
def new_int_vars(min, max, count = 1)
|
15
|
+
int_var_store.new_vars(min, max, count)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Gets the int variable with the specified index, nil if none exists.
|
19
|
+
def int_var(index)
|
20
|
+
int_var_store[index]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Creates the specified number of boolean variables in the space. Returns
|
24
|
+
# the indices with which they can then be accessed using int_var.
|
25
|
+
def new_bool_vars(count = 1)
|
26
|
+
bool_var_store.new_vars(count)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Gets the int variable with the specified index, nil if none exists.
|
30
|
+
def bool_var(index)
|
31
|
+
bool_var_store[index]
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Retrieves the store used for integer variables. Creates one if none
|
37
|
+
# exists.
|
38
|
+
def int_var_store
|
39
|
+
if @int_var_store.nil?
|
40
|
+
@int_var_store = Gecode::Util::IntVarStore.new(self)
|
41
|
+
end
|
42
|
+
return @int_var_store
|
43
|
+
end
|
44
|
+
|
45
|
+
# Retrieves the store used for boolean variables. Creates one if none
|
46
|
+
# exists.
|
47
|
+
def bool_var_store
|
48
|
+
if @bool_var_store.nil?
|
49
|
+
@bool_var_store = Gecode::Util::BoolVarStore.new(self)
|
50
|
+
end
|
51
|
+
return @bool_var_store
|
52
|
+
end
|
15
53
|
end
|
16
54
|
|
17
|
-
|
18
|
-
|
19
|
-
|
55
|
+
class IntVar
|
56
|
+
# Aliases to make method-names more ruby-like.
|
57
|
+
alias_method :assigned?, :assigned
|
58
|
+
alias_method :in?, :in
|
59
|
+
alias_method :include?, :in
|
60
|
+
alias_method :range?, :range
|
20
61
|
end
|
21
62
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
@int_var_store = Gecode::Raw::IntVarStore.new(self)
|
63
|
+
class BoolVar
|
64
|
+
# Aliases to make method-names more ruby-like.
|
65
|
+
alias_method :assigned?, :assigned
|
66
|
+
|
67
|
+
def true?
|
68
|
+
val == 1
|
29
69
|
end
|
30
|
-
return @int_var_store
|
31
70
|
end
|
32
71
|
end
|
33
|
-
|
34
|
-
# A store in which int variables are created and stored.
|
35
|
-
class IntVarStore
|
36
|
-
# Design note: The store used to double its size when it needed to grow
|
37
|
-
# leaving unallocated slots (in rev 16). This was changed to only growing
|
38
|
-
# the amount of space needed because the additional information about which
|
39
|
-
# slot is the next unallocated one could not be encoded without changes to
|
40
|
-
# the bindings (and without that information we can not deduce the store
|
41
|
-
# from the new copy of space). So for additional performance the bindings
|
42
|
-
# should grow the array more than needed (when this is moved to the bindings).
|
43
|
-
|
44
|
-
private
|
45
72
|
|
46
|
-
|
47
|
-
|
73
|
+
# Various utility (mainly used to change the behavior of the raw bindings).
|
74
|
+
module Util
|
75
|
+
# Provides common methods to the variable stores. The stores must provide
|
76
|
+
# @next_index, @var_array, @size, ARRAY_IDENTIFIER and #new_storage_array .
|
77
|
+
module VarStoreMethods
|
78
|
+
# Returns the int var with the specified index, nil if none exists.
|
79
|
+
def [](index)
|
80
|
+
if index < 0 or index >= @next_index
|
81
|
+
return nil
|
82
|
+
end
|
83
|
+
return @var_array.at(index)
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Grows the store to the new size.
|
89
|
+
def grow(new_size)
|
90
|
+
new_array = new_storage_array(new_size)
|
91
|
+
@var_array.size.times do |i|
|
92
|
+
new_array[i] = @var_array[i]
|
93
|
+
end
|
94
|
+
@var_array = new_array
|
95
|
+
@size = new_size
|
96
|
+
end
|
97
|
+
end
|
48
98
|
|
49
|
-
|
99
|
+
# A store in which int variables are created and stored.
|
100
|
+
class IntVarStore
|
101
|
+
# Design note: The store used to double its size when it needed to grow
|
102
|
+
# leaving unallocated slots (in rev 16). This was changed to only growing
|
103
|
+
# the amount of space needed because the additional information about which
|
104
|
+
# slot is the next unallocated one could not be encoded without changes to
|
105
|
+
# the bindings (and without that information we can not deduce the store
|
106
|
+
# from the new copy of space). So for additional performance the bindings
|
107
|
+
# should grow the array more than needed (when this is moved to the bindings).
|
108
|
+
|
109
|
+
include VarStoreMethods
|
110
|
+
|
111
|
+
private
|
50
112
|
|
51
|
-
|
52
|
-
|
53
|
-
@var_array = space.int_var_array(ARRAY_IDENTIFIER)
|
54
|
-
if @var_array.nil?
|
55
|
-
# Create a new one.
|
56
|
-
@var_array = Gecode::Raw::IntVarArray.new(space, 0)
|
57
|
-
space.own(@var_array, ARRAY_IDENTIFIER)
|
58
|
-
end
|
59
|
-
|
60
|
-
@size = @var_array.size
|
61
|
-
@next_index = @size
|
62
|
-
@space = space
|
63
|
-
end
|
113
|
+
# A string that identifies the array used by the store.
|
114
|
+
ARRAY_IDENTIFIER = 'int_array'
|
64
115
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
@
|
116
|
+
public
|
117
|
+
|
118
|
+
# Creates a store for the specified space with the specified capacit.
|
119
|
+
def initialize(space)
|
120
|
+
@space = space
|
121
|
+
|
122
|
+
@var_array = space.int_var_array(ARRAY_IDENTIFIER)
|
123
|
+
if @var_array.nil?
|
124
|
+
# Create a new one.
|
125
|
+
@var_array = new_storage_array(0)
|
126
|
+
end
|
127
|
+
|
128
|
+
@size = @var_array.size
|
129
|
+
@next_index = @size
|
73
130
|
end
|
74
131
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
132
|
+
# Creates the specified number of new int variables with the specified
|
133
|
+
# range as domain. Returns the indices of the created variables as an array.
|
134
|
+
def new_vars(min, max, count = 1)
|
135
|
+
grow(@next_index + count) # See the design note for more information.
|
136
|
+
count.times do |i|
|
137
|
+
@var_array[@next_index] = Gecode::Raw::IntVar.new(@space,
|
138
|
+
min, max)
|
139
|
+
@next_index += 1
|
140
|
+
end
|
141
|
+
|
142
|
+
((@next_index - count)...@next_index).to_a
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns the int var with the specified index, nil if none exists.
|
146
|
+
def [](index)
|
147
|
+
if index < 0 or index >= @next_index
|
148
|
+
return nil
|
149
|
+
end
|
150
|
+
return @var_array.at(index)
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
# Creates a new storage array for int variables.
|
156
|
+
def new_storage_array(new_size)
|
157
|
+
arr = Gecode::Raw::IntVarArray.new(@space, new_size)
|
158
|
+
@space.own(arr, ARRAY_IDENTIFIER)
|
159
|
+
return arr
|
82
160
|
end
|
83
|
-
return @var_array.at(index)
|
84
161
|
end
|
85
|
-
|
86
|
-
private
|
87
162
|
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
|
163
|
+
# A store in which int variables are created and stored.
|
164
|
+
class BoolVarStore
|
165
|
+
# TODO: can we refactor this better seeing as IntVarStore and BoolVarStore
|
166
|
+
# are similar?
|
167
|
+
|
168
|
+
include VarStoreMethods
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
# A string that identifies the array used by the store.
|
173
|
+
ARRAY_IDENTIFIER = 'bool_array'
|
174
|
+
|
175
|
+
public
|
176
|
+
|
177
|
+
# Creates a store for the specified space with the specified capacit.
|
178
|
+
def initialize(space)
|
179
|
+
@space = space
|
180
|
+
|
181
|
+
@var_array = space.bool_var_array(ARRAY_IDENTIFIER)
|
182
|
+
if @var_array.nil?
|
183
|
+
# Create a new one.
|
184
|
+
@var_array = new_storage_array(0)
|
185
|
+
end
|
186
|
+
|
187
|
+
@size = @var_array.size
|
188
|
+
@next_index = @size
|
92
189
|
end
|
93
190
|
|
94
|
-
|
95
|
-
|
96
|
-
|
191
|
+
# Creates the specified number of new bool variables. Returns the indices
|
192
|
+
# of the created variables as an array.
|
193
|
+
def new_vars(count = 1)
|
194
|
+
grow(@next_index + count) # See the design note for more information.
|
195
|
+
count.times do |i|
|
196
|
+
@var_array[@next_index] = Gecode::Raw::BoolVar.new(@space, 0, 1)
|
197
|
+
@next_index += 1
|
198
|
+
end
|
199
|
+
|
200
|
+
((@next_index - count)...@next_index).to_a
|
97
201
|
end
|
98
|
-
@space.own(new_array, ARRAY_IDENTIFIER)
|
99
|
-
@var_array = new_array
|
100
|
-
@size = new_size
|
101
|
-
end
|
102
|
-
end
|
103
202
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
203
|
+
private
|
204
|
+
|
205
|
+
# Creates a new storage array for bool variables.
|
206
|
+
def new_storage_array(new_size)
|
207
|
+
arr = Gecode::Raw::BoolVarArray.new(@space, new_size)
|
208
|
+
@space.own(arr, ARRAY_IDENTIFIER)
|
209
|
+
return arr
|
210
|
+
end
|
211
|
+
end
|
109
212
|
end
|
110
213
|
end
|
111
|
-
|