gecoder 0.6.0 → 0.6.1

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.
Files changed (45) hide show
  1. data/CHANGES +9 -1
  2. data/Rakefile +3 -0
  3. data/example/send_most_money.rb +58 -0
  4. data/ext/missing.cpp +26 -1
  5. data/ext/missing.h +2 -0
  6. data/ext/vararray.cpp +31 -11
  7. data/ext/vararray.h +6 -0
  8. data/lib/gecoder/bindings.rb +5 -5
  9. data/lib/gecoder/bindings/bindings.rb +52 -0
  10. data/lib/gecoder/interface/binding_changes.rb +16 -11
  11. data/lib/gecoder/interface/constraints.rb +28 -15
  12. data/lib/gecoder/interface/constraints/bool_enum/boolean.rb +8 -17
  13. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +8 -3
  14. data/lib/gecoder/interface/constraints/int/arithmetic.rb +10 -15
  15. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +10 -16
  16. data/lib/gecoder/interface/constraints/int_enum/element.rb +6 -11
  17. data/lib/gecoder/interface/constraints/int_var_constraints.rb +2 -1
  18. data/lib/gecoder/interface/constraints/set/cardinality.rb +4 -7
  19. data/lib/gecoder/interface/constraints/set/connection.rb +13 -22
  20. data/lib/gecoder/interface/model.rb +52 -41
  21. data/lib/gecoder/interface/search.rb +29 -24
  22. data/lib/gecoder/interface/variables.rb +27 -15
  23. data/lib/gecoder/version.rb +1 -1
  24. data/specs/constraints/arithmetic.rb +27 -17
  25. data/specs/constraints/bool_enum.rb +4 -2
  26. data/specs/constraints/boolean.rb +5 -2
  27. data/specs/constraints/cardinality.rb +28 -8
  28. data/specs/constraints/connection.rb +58 -37
  29. data/specs/constraints/constraints.rb +2 -2
  30. data/specs/constraints/count.rb +3 -3
  31. data/specs/constraints/element.rb +5 -5
  32. data/specs/constraints/int_domain.rb +4 -2
  33. data/specs/constraints/set_domain.rb +8 -4
  34. data/specs/constraints/set_relation.rb +10 -5
  35. data/specs/int_var.rb +3 -3
  36. data/specs/model.rb +10 -9
  37. data/specs/search.rb +54 -5
  38. data/specs/spec_helper.rb +2 -0
  39. data/tasks/distribution.rake +8 -1
  40. data/tasks/specs.rake +0 -1
  41. data/vendor/rust/rust/class.rb +6 -1
  42. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +3 -3
  43. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +15 -1
  44. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +2 -0
  45. metadata +51 -21
data/CHANGES CHANGED
@@ -1,3 +1,11 @@
1
+ == Version 0.6.1
2
+ This release fixes various bugs introduced in 0.6.0 and changes the way that
3
+ int variable domains are specified (breaking backward-compatibility).
4
+
5
+ * The domain for int variables can no longer be specified as several individual elements, it has to be specified as either a single element, a range or another enumeration.
6
+ * Fixed a bug with set cardinality, min and max constraints using composite sugar.
7
+ * Variables can now be created inside the optimization block.
8
+
1
9
  == Version 0.6.0
2
10
  This release adds most of the remaining set constraints. It also makes
3
11
  backward-compatibility breaking changes to the way that properties of variables
@@ -9,7 +17,7 @@ are accessed.
9
17
  * Added include (match) constraint for sets.
10
18
  * Added distinct constraints (distinct and at most one) for sets.
11
19
  * Added branch and bound search (optimization search). It's quite shaky at the moment though.
12
- * Assigned values of variables are now always accessed using #value instread of the various previous methods. The methods for extracting information from set variables have been changed and renamed.
20
+ * Assigned values of variables are now always accessed using #value instead of the various previous methods. The methods for extracting information from set variables have been changed and renamed.
13
21
  * Enumerations containing variables now provide a convenience method #values which returns an array of the enum's values.
14
22
 
15
23
  == Version 0.5.0
data/Rakefile CHANGED
@@ -8,3 +8,6 @@ task :default => [:verify_rcov]
8
8
 
9
9
  desc 'Performs the tasks necessary when releasing'
10
10
  task :release => [:publish_website, :publish_packages, :tag]
11
+
12
+ desc 'Runs all the tests'
13
+ task :test => :specs
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/example_helper'
2
+
3
+ # Solves the cryptarithmetic send+most=money problem while maximizing the value
4
+ # of "money".
5
+ class SendMoreMoney < Gecode::Model
6
+ attr :money
7
+
8
+ def initialize
9
+ # Set up the variables, 9 letters with domain 0..9.
10
+ s,e,n,d,m,o,s,t,y = @letters = int_var_array(9, 0..9)
11
+ @money = wrap_enum([m,o,n,e,y])
12
+
13
+ # Set up the constraints.
14
+ # The equation must hold.
15
+ (equation_row(s, e, n, d) + equation_row(m, o, s, t)).must ==
16
+ equation_row(m,o,n,e,y)
17
+
18
+ # The initial letters may not be 0.
19
+ s.must_not == 0
20
+ m.must_not == 0
21
+
22
+ # All letters must be assigned different digits.
23
+ @letters.must_be.distinct
24
+
25
+ # Set the branching.
26
+ branch_on @letters, :variable => :smallest_size, :value => :min
27
+ end
28
+
29
+ def to_s
30
+ %w{s e n d m o s t y}.zip(@letters).map do |text, letter|
31
+ "#{text}: #{letter.value}"
32
+ end.join(', ')
33
+ end
34
+
35
+ private
36
+
37
+ # A helper to make the linear equation a bit tidier. Takes a number of
38
+ # variables and computes the linear combination as if the variable
39
+ # were digits in a base 10 number. E.g. x,y,z becomes
40
+ # 100*x + 10*y + z .
41
+ def equation_row(*variables)
42
+ variables.to_number
43
+ end
44
+ end
45
+
46
+ class Array
47
+ # Computes a number of the specified base using the array's elements as
48
+ # digits.
49
+ def to_number(base = 10)
50
+ inject{ |result, variable| variable + result * base }
51
+ end
52
+ end
53
+
54
+ solution = SendMoreMoney.new.optimize! do |model, best_so_far|
55
+ model.money.to_number.must > best_so_far.money.values.to_number
56
+ end
57
+ puts solution.to_s
58
+ puts "money: #{solution.money.values.to_number}"
data/ext/missing.cpp CHANGED
@@ -194,12 +194,37 @@ void MSpace::own(Gecode::MSetVarArray *sva, const char *name)
194
194
  d->setArrays[name] = sva;
195
195
  }
196
196
 
197
+ void MSpace::gc_mark()
198
+ {
199
+ {
200
+ IntVarArrays::iterator it, eend = d->intArrays.end();
201
+ for(it = d->intArrays.begin(); it != eend; it++)
202
+ {
203
+ rb_gc_mark(Rust_gecode::cxx2ruby((*it).second));
204
+ }
205
+ }
206
+ {
207
+ BoolVarArrays::iterator it, eend = d->boolArrays.end();
208
+ for(it = d->boolArrays.begin(); it != eend; it++)
209
+ {
210
+ rb_gc_mark(Rust_gecode::cxx2ruby((*it).second));
211
+ }
212
+ }
213
+ {
214
+ SetVarArrays::iterator it, eend = d->setArrays.end();
215
+ for(it = d->setArrays.begin(); it != eend; it++)
216
+ {
217
+ rb_gc_mark(Rust_gecode::cxx2ruby((*it).second));
218
+ }
219
+ }
220
+ }
221
+
197
222
  // For BAB.
198
223
  void MSpace::constrain(MSpace* s)
199
224
  {
200
225
  // Call Ruby's constrain.
201
226
  rb_funcall(Rust_gecode::cxx2ruby(this), rb_intern("constrain"), 1,
202
- Rust_gecode::cxx2ruby(s));
227
+ Rust_gecode::cxx2ruby(s, false));
203
228
  }
204
229
 
205
230
  Gecode::MIntVarArray *MSpace::intVarArray(const char *name) const
data/ext/missing.h CHANGED
@@ -61,6 +61,8 @@ class MSpace : public Space
61
61
  void own(Gecode::MBoolVarArray *bva, const char *name);
62
62
  void own(Gecode::MSetVarArray *sva, const char *name);
63
63
 
64
+ void gc_mark();
65
+
64
66
  void constrain(MSpace* s);
65
67
 
66
68
  Gecode::MIntVarArray *intVarArray(const char *name ) const;
data/ext/vararray.cpp CHANGED
@@ -18,6 +18,7 @@
18
18
  **/
19
19
 
20
20
  #include "vararray.h"
21
+ #include "gecode.hh"
21
22
 
22
23
  namespace Gecode {
23
24
 
@@ -74,7 +75,6 @@ MIntVarArray::MIntVarArray() : d(new Private)
74
75
  MIntVarArray::MIntVarArray(const Gecode::IntVarArray &arr) : d(new Private)
75
76
  {
76
77
  setArray(arr);
77
- setCount(0);
78
78
  }
79
79
 
80
80
  MIntVarArray::MIntVarArray (Space *home, int n) : d(new Private)
@@ -107,7 +107,7 @@ void MIntVarArray::setArray(const Gecode::IntVarArray &arr)
107
107
  void MIntVarArray::enlargeArray(Gecode::Space *parent, int n)
108
108
  {
109
109
  Gecode::IntVarArray na(parent, size()+n, 0, 0);
110
- for(int i = count(); i--; )
110
+ for(int i = size(); i--; )
111
111
  na[i] = d->array[i];
112
112
 
113
113
  d->array = na;
@@ -130,6 +130,13 @@ IntVar &MIntVarArray::operator [](int index)
130
130
  return d->array[index];
131
131
  }
132
132
 
133
+ void MIntVarArray::gc_mark()
134
+ {
135
+ for(int i = size(); i--; ) {
136
+ rb_gc_mark(Rust_gecode::cxx2ruby(&(d->array[i])));
137
+ }
138
+ }
139
+
133
140
  void MIntVarArray::debug() const
134
141
  {
135
142
  for(int i = 0; i < d->array.size(); i++)
@@ -150,14 +157,14 @@ struct MBoolVarArray::Private
150
157
 
151
158
  MBoolVarArray::MBoolVarArray() : d(new Private)
152
159
  {
160
+ setArray(Gecode::BoolVarArray());
153
161
  }
154
162
 
155
163
  MBoolVarArray::MBoolVarArray(const Gecode::BoolVarArray &arr) : d(new Private)
156
164
  {
157
- d->array = arr;
158
- setSize(arr.size());
159
- setCount(0);
165
+ setArray(arr);
160
166
  }
167
+
161
168
  MBoolVarArray::MBoolVarArray (Space *home, int n) : d(new Private)
162
169
  {
163
170
  setArray(Gecode::BoolVarArray(home, n));
@@ -177,7 +184,7 @@ void MBoolVarArray::setArray(const Gecode::BoolVarArray &arr)
177
184
  void MBoolVarArray::enlargeArray(Gecode::Space *parent, int n)
178
185
  {
179
186
  Gecode::BoolVarArray na(parent, size()+n, 0, 0);
180
- for(int i = count(); i--; )
187
+ for(int i = size(); i--; )
181
188
  na[i] = d->array[i];
182
189
 
183
190
  d->array = na;
@@ -200,6 +207,13 @@ Gecode::BoolVar &MBoolVarArray::operator[](int index)
200
207
  return d->array[index];
201
208
  }
202
209
 
210
+ void MBoolVarArray::gc_mark()
211
+ {
212
+ for(int i = size(); i--; ) {
213
+ rb_gc_mark(Rust_gecode::cxx2ruby(&(d->array[i])));
214
+ }
215
+ }
216
+
203
217
  void MBoolVarArray::debug() const
204
218
  {
205
219
  for(int i = 0; i < d->array.size(); i++)
@@ -219,13 +233,12 @@ struct MSetVarArray::Private
219
233
 
220
234
  MSetVarArray::MSetVarArray() : d(new Private)
221
235
  {
236
+ setArray(Gecode::SetVarArray());
222
237
  }
223
238
 
224
239
  MSetVarArray::MSetVarArray(const Gecode::SetVarArray &arr) : d(new Private)
225
240
  {
226
- d->array = arr;
227
- setSize(arr.size());
228
- setCount(0);
241
+ setArray(arr);
229
242
  }
230
243
 
231
244
  MSetVarArray::MSetVarArray(Space *home, int n) : d(new Private)
@@ -266,8 +279,8 @@ void MSetVarArray::setArray(const Gecode::SetVarArray &arr)
266
279
 
267
280
  void MSetVarArray::enlargeArray(Gecode::Space *parent, int n)
268
281
  {
269
- Gecode::SetVarArray na(parent, size()*n);
270
- for (int i = count(); i--; )
282
+ Gecode::SetVarArray na(parent, size()+n);
283
+ for (int i = size(); i--; )
271
284
  na[i] = d->array[i];
272
285
 
273
286
  d->array = na;
@@ -290,6 +303,13 @@ Gecode::SetVar &MSetVarArray::operator[](int index)
290
303
  return d->array[index];
291
304
  }
292
305
 
306
+ void MSetVarArray::gc_mark()
307
+ {
308
+ for(int i = size(); i--; ) {
309
+ rb_gc_mark(Rust_gecode::cxx2ruby(&(d->array[i])));
310
+ }
311
+ }
312
+
293
313
  void MSetVarArray::debug() const
294
314
  {
295
315
  for(int i = 0; i < d->array.size(); i++)
data/ext/vararray.h CHANGED
@@ -65,6 +65,8 @@ class MIntVarArray : public MVarArray
65
65
 
66
66
  void debug() const;
67
67
 
68
+ void gc_mark();
69
+
68
70
  IntVar &operator [](int index);
69
71
 
70
72
  private:
@@ -93,6 +95,8 @@ class MBoolVarArray : public MVarArray
93
95
 
94
96
  void debug() const;
95
97
 
98
+ void gc_mark();
99
+
96
100
  private:
97
101
  struct Private;
98
102
  Private *const d;
@@ -131,6 +135,8 @@ class MSetVarArray : public MVarArray
131
135
 
132
136
  void debug() const;
133
137
 
138
+ void gc_mark();
139
+
134
140
  private:
135
141
  struct Private;
136
142
  Private *const d;
@@ -3,11 +3,6 @@ module Gecode
3
3
  # The Gecode::Raw module is what the interface should use to access methods
4
4
  # in Gecode. The actual bindings are located in ::GecodeRaw.
5
5
 
6
- # We just make Gecode::Raw an alias of the real module.
7
- Raw = ::GecodeRaw
8
- # Log all calls via Gecode::Raw.
9
- #Raw = ::LoggingLayer
10
-
11
6
  # Describes a layer that delegates to GecodeRaw only after having logged the
12
7
  # call.
13
8
  module LoggingLayer
@@ -31,4 +26,9 @@ module Gecode
31
26
  @logger
32
27
  end
33
28
  end
29
+
30
+ # We just make Gecode::Raw an alias of the real module.
31
+ Raw = ::GecodeRaw
32
+ # Log all calls via Gecode::Raw.
33
+ #Raw = LoggingLayer
34
34
  end
@@ -48,6 +48,28 @@ Gecode::IntArgs ruby2Gecode_IntArgs(VALUE arr, int argn)
48
48
  }
49
49
  @
50
50
 
51
+ custom_mark_definitions =<<-"end_custom_definition"
52
+ static void Gecode_MSpace_custom_mark(void *p) {
53
+ Gecode_MSpace_mark(p);
54
+ ((Gecode::MSpace*)p)->gc_mark();
55
+ }
56
+
57
+ static void Gecode_MIntVarArray_custom_mark(void *p) {
58
+ Gecode_MIntVarArray_mark(p);
59
+ ((Gecode::MIntVarArray*)p)->gc_mark();
60
+ }
61
+
62
+ static void Gecode_MBoolVarArray_custom_mark(void *p) {
63
+ Gecode_MBoolVarArray_mark(p);
64
+ ((Gecode::MBoolVarArray*)p)->gc_mark();
65
+ }
66
+
67
+ static void Gecode_MSetVarArray_custom_mark(void *p) {
68
+ Gecode_MSetVarArray_mark(p);
69
+ ((Gecode::MSetVarArray*)p)->gc_mark();
70
+ }
71
+ end_custom_definition
72
+
51
73
 
52
74
  Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
53
75
  b.include_header 'gecode/kernel.hh', Rust::Bindings::HeaderGlobal
@@ -57,6 +79,7 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
57
79
  b.include_header 'missing.h', Rust::Bindings::HeaderLocal
58
80
 
59
81
  b.add_custom_definition ruby2intargs
82
+ b.add_custom_definition custom_mark_definitions
60
83
 
61
84
  # Is it possible to use namespaces with multiple levels in Rust? I.e. use
62
85
  # Gecode::Raw instead of GecodeRaw here (and avoid the hidious renaming)
@@ -146,6 +169,8 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
146
169
 
147
170
  ns.add_cxx_class "MIntVarArray" do |klass|
148
171
  klass.bindname = "IntVarArray"
172
+ klass.function_mark = 'Gecode_MIntVarArray_custom_mark'
173
+
149
174
  klass.add_constructor
150
175
  klass.add_constructor do |func|
151
176
  func.add_parameter "Gecode::MSpace *", "home"
@@ -178,6 +203,11 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
178
203
  method.add_parameter "Gecode::IntVar", "val"
179
204
  end
180
205
 
206
+ klass.add_method "enlargeArray" do |method|
207
+ method.add_parameter "Gecode::MSpace *", "home"
208
+ method.add_parameter "int", "n"
209
+ end
210
+
181
211
  klass.add_method "size", "int"
182
212
 
183
213
  klass.add_method "debug"
@@ -187,6 +217,8 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
187
217
 
188
218
  ns.add_cxx_class "MBoolVarArray" do |klass|
189
219
  klass.bindname = "BoolVarArray"
220
+ klass.function_mark = 'Gecode_MBoolVarArray_custom_mark'
221
+
190
222
  klass.add_constructor
191
223
  klass.add_constructor do |func|
192
224
  func.add_parameter "Gecode::MSpace *", "home"
@@ -206,6 +238,11 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
206
238
  method.add_parameter "Gecode::BoolVar", "val"
207
239
  end
208
240
 
241
+ klass.add_method "enlargeArray" do |method|
242
+ method.add_parameter "Gecode::MSpace *", "home"
243
+ method.add_parameter "int", "n"
244
+ end
245
+
209
246
  klass.add_method "size", "int"
210
247
 
211
248
  klass.add_method "debug"
@@ -214,6 +251,8 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
214
251
 
215
252
  ns.add_cxx_class "MSetVarArray" do |klass|
216
253
  klass.bindname = "SetVarArray"
254
+ klass.function_mark = 'Gecode_MSetVarArray_custom_mark'
255
+
217
256
  klass.add_constructor
218
257
 
219
258
  klass.add_constructor do |method|
@@ -274,6 +313,11 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
274
313
  method.add_parameter "Gecode::SetVar", "val"
275
314
  end
276
315
 
316
+ klass.add_method "enlargeArray" do |method|
317
+ method.add_parameter "Gecode::MSpace *", "home"
318
+ method.add_parameter "int", "n"
319
+ end
320
+
277
321
  klass.add_method "size", "int"
278
322
 
279
323
  klass.add_method "debug"
@@ -288,6 +332,7 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
288
332
 
289
333
  ns.add_cxx_class "MSpace" do |klass|
290
334
  klass.bindname = "Space"
335
+ klass.function_mark = 'Gecode_MSpace_custom_mark'
291
336
 
292
337
  klass.add_constructor
293
338
 
@@ -1429,6 +1474,13 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
1429
1474
  # func.add_parameter "Gecode::IntConLevel", "icl", true
1430
1475
  # end
1431
1476
 
1477
+ ns.add_function "bab", "Gecode::MSpace*" do |func|
1478
+ func.add_parameter "Gecode::MSpace*", "home"
1479
+ func.add_parameter "int", "c_d"
1480
+ func.add_parameter "int", "a_d"
1481
+ func.add_parameter "Gecode::Search::MStop *", "st"
1482
+ end
1483
+
1432
1484
  ns.add_function "rel" do |func|
1433
1485
  func.add_parameter "Gecode::MSpace*", "home"
1434
1486
  func.add_parameter "Gecode::IntVar", "x0"
@@ -52,31 +52,40 @@ module GecodeRaw
52
52
  Gecode::Model.constrain(self, best_so_far_space)
53
53
  end
54
54
 
55
+ # Refreshes the underlying stores used by the space.
56
+ def refresh
57
+ @int_var_store = nil
58
+ @bool_var_store = nil
59
+ @set_var_store = nil
60
+ end
61
+
55
62
  private
56
63
 
57
64
  # Retrieves the store used for integer variables. Creates one if none
58
65
  # exists.
59
66
  def int_var_store
60
- if @int_var_store.nil?
67
+ # TODO: caching interferes with the variable creation during BAB-search,
68
+ # find out why.
69
+ #if @int_var_store.nil?
61
70
  @int_var_store = Gecode::Util::IntVarStore.new(self)
62
- end
71
+ #end
63
72
  return @int_var_store
64
73
  end
65
74
 
66
75
  # Retrieves the store used for boolean variables. Creates one if none
67
76
  # exists.
68
77
  def bool_var_store
69
- if @bool_var_store.nil?
78
+ #if @bool_var_store.nil?
70
79
  @bool_var_store = Gecode::Util::BoolVarStore.new(self)
71
- end
80
+ #end
72
81
  return @bool_var_store
73
82
  end
74
83
 
75
84
  # Retrieves the store used for set variables. Creates one if none exists.
76
85
  def set_var_store
77
- if @set_var_store.nil?
86
+ #if @set_var_store.nil?
78
87
  @set_var_store = Gecode::Util::SetVarStore.new(self)
79
- end
88
+ #end
80
89
  return @set_var_store
81
90
  end
82
91
  end
@@ -100,11 +109,7 @@ module Gecode
100
109
 
101
110
  # Grows the store to the new size.
102
111
  def grow(new_size)
103
- new_array = new_storage_array(new_size)
104
- @var_array.size.times do |i|
105
- new_array[i] = @var_array[i]
106
- end
107
- @var_array = new_array
112
+ @var_array.enlargeArray(@space, new_size - @size)
108
113
  @size = new_size
109
114
  end
110
115
  end