gecoder 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +16 -3
- data/example/magic_sequence.rb +1 -1
- data/example/queens.rb +1 -1
- data/example/send_more_money.rb +1 -1
- data/example/sudoku.rb +1 -1
- data/ext/missing.cpp +18 -4
- data/ext/missing.h +8 -0
- data/lib/gecoder/bindings.rb +30 -3
- data/lib/gecoder/bindings/bindings.rb +22 -0
- data/lib/gecoder/interface/binding_changes.rb +81 -107
- data/lib/gecoder/interface/branch.rb +65 -14
- data/lib/gecoder/interface/constraints.rb +1 -0
- data/lib/gecoder/interface/constraints/bool_enum/boolean.rb +16 -12
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +7 -3
- data/lib/gecoder/interface/constraints/int/linear.rb +19 -16
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +8 -4
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +14 -6
- data/lib/gecoder/interface/constraints/int_enum/element.rb +7 -5
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +1 -4
- data/lib/gecoder/interface/constraints/set/cardinality.rb +6 -3
- data/lib/gecoder/interface/constraints/set/connection.rb +136 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +18 -0
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +61 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +32 -0
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +1 -0
- data/lib/gecoder/interface/enum_wrapper.rb +12 -3
- data/lib/gecoder/interface/model.rb +77 -56
- data/lib/gecoder/interface/search.rb +74 -5
- data/lib/gecoder/interface/variables.rb +117 -15
- data/lib/gecoder/version.rb +1 -1
- data/specs/binding_changes.rb +9 -5
- data/specs/bool_var.rb +8 -12
- data/specs/branch.rb +85 -19
- data/specs/constraints/arithmetic.rb +99 -71
- data/specs/constraints/bool_enum.rb +26 -18
- data/specs/constraints/boolean.rb +53 -49
- data/specs/constraints/cardinality.rb +33 -26
- data/specs/constraints/channel.rb +77 -6
- data/specs/constraints/connection.rb +352 -0
- data/specs/constraints/constraints.rb +10 -1
- data/specs/constraints/count.rb +79 -39
- data/specs/constraints/distinct.rb +128 -9
- data/specs/constraints/element.rb +26 -19
- data/specs/constraints/equality.rb +2 -1
- data/specs/constraints/int_domain.rb +19 -12
- data/specs/constraints/int_relation.rb +12 -6
- data/specs/constraints/linear.rb +30 -30
- data/specs/constraints/reification_sugar.rb +8 -4
- data/specs/constraints/set_domain.rb +24 -18
- data/specs/constraints/set_relation.rb +38 -23
- data/specs/constraints/sort.rb +12 -10
- data/specs/enum_wrapper.rb +9 -3
- data/specs/int_var.rb +8 -4
- data/specs/logging.rb +24 -0
- data/specs/model.rb +25 -7
- data/specs/search.rb +41 -1
- data/specs/set_var.rb +36 -7
- data/specs/spec_helper.rb +3 -10
- data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +1 -1
- metadata +12 -3
- data/specs/tmp +0 -22
data/CHANGES
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
== Version 0.6.0
|
2
|
+
This release adds most of the remaining set constraints. It also makes
|
3
|
+
backward-compatibility breaking changes to the way that properties of variables
|
4
|
+
are accessed.
|
5
|
+
|
6
|
+
* Added channel constraints involving set variables.
|
7
|
+
* Added set min and max constraints.
|
8
|
+
* Added set sum constraints (optionally weighted or substituted).
|
9
|
+
* Added include (match) constraint for sets.
|
10
|
+
* Added distinct constraints (distinct and at most one) for sets.
|
11
|
+
* 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.
|
13
|
+
* Enumerations containing variables now provide a convenience method #values which returns an array of the enum's values.
|
14
|
+
|
1
15
|
== Version 0.5.0
|
2
16
|
This release adds set variables and some of their constraints, along with the
|
3
17
|
last of the boolean constraints.
|
@@ -10,10 +24,9 @@ last of the boolean constraints.
|
|
10
24
|
* Added set cardinality constraints.
|
11
25
|
|
12
26
|
== Version 0.4.0
|
13
|
-
This release adds most of the constraints supported by Gecode
|
14
|
-
variables.
|
27
|
+
This release adds most of the integer variable constraints supported by Gecode.
|
15
28
|
|
16
|
-
* [#11861] Fixed a bug stopping the
|
29
|
+
* [#11861] Fixed a bug stopping the creation of int variables with non-range domains.
|
17
30
|
* Added domain constraints for int variables.
|
18
31
|
* Added equality constraint for int enums.
|
19
32
|
* Matrices of integer and boolean variables can now be created using Model#int_var_matrix Model#bool_var_matrix.
|
data/example/magic_sequence.rb
CHANGED
data/example/queens.rb
CHANGED
@@ -25,7 +25,7 @@ class NQueens < Gecode::Model
|
|
25
25
|
|
26
26
|
# Displays the assignment as a chessboard with queens denoted by 'x'.
|
27
27
|
def to_s
|
28
|
-
rows = @queen_rows.
|
28
|
+
rows = @queen_rows.values
|
29
29
|
|
30
30
|
separator = '+' << '-' * (3 * @size + (@size - 1)) << "+\n"
|
31
31
|
res = (0...@size).inject(separator) do |s, i|
|
data/example/send_more_money.rb
CHANGED
data/example/sudoku.rb
CHANGED
@@ -44,7 +44,7 @@ class Sudoku < Gecode::Model
|
|
44
44
|
separator = '+' << '-' * (3 * @size + (@size - 1)) << "+\n"
|
45
45
|
res = (0...@size).inject(separator) do |s, i|
|
46
46
|
(0...@size).inject(s + '|') do |s, j|
|
47
|
-
s << " #{@squares[i,j].
|
47
|
+
s << " #{@squares[i,j].value} |"
|
48
48
|
end << "\n" << separator
|
49
49
|
end
|
50
50
|
end
|
data/ext/missing.cpp
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
**/
|
19
19
|
|
20
20
|
#include "missing.h"
|
21
|
+
#include "gecode.hh"
|
21
22
|
|
22
23
|
#include <iostream>
|
23
24
|
#include <map>
|
@@ -193,6 +194,14 @@ void MSpace::own(Gecode::MSetVarArray *sva, const char *name)
|
|
193
194
|
d->setArrays[name] = sva;
|
194
195
|
}
|
195
196
|
|
197
|
+
// For BAB.
|
198
|
+
void MSpace::constrain(MSpace* s)
|
199
|
+
{
|
200
|
+
// Call Ruby's constrain.
|
201
|
+
rb_funcall(Rust_gecode::cxx2ruby(this), rb_intern("constrain"), 1,
|
202
|
+
Rust_gecode::cxx2ruby(s));
|
203
|
+
}
|
204
|
+
|
196
205
|
Gecode::MIntVarArray *MSpace::intVarArray(const char *name) const
|
197
206
|
{
|
198
207
|
if ( d->intArrays.find(name) == d->intArrays.end() ) return 0;
|
@@ -211,7 +220,6 @@ Gecode::MSetVarArray *MSpace::setVarArray(const char *name ) const
|
|
211
220
|
return d->setArrays[name];
|
212
221
|
}
|
213
222
|
|
214
|
-
|
215
223
|
Gecode::MBranchingDesc *MSpace::mdescription()
|
216
224
|
{
|
217
225
|
if(!this->failed() || !d->description->ptr() )
|
@@ -237,6 +245,15 @@ MDFS::~MDFS()
|
|
237
245
|
}
|
238
246
|
|
239
247
|
|
248
|
+
// BAB
|
249
|
+
MBAB::MBAB(MSpace *space, unsigned int c_d, unsigned int a_d, Search::Stop* st) : Gecode::BAB<MSpace>(space, c_d, a_d, st)
|
250
|
+
{
|
251
|
+
}
|
252
|
+
|
253
|
+
MBAB::~MBAB()
|
254
|
+
{
|
255
|
+
}
|
256
|
+
|
240
257
|
namespace Search {
|
241
258
|
|
242
259
|
// Stop
|
@@ -284,6 +301,3 @@ Gecode::Search::Stop* MStop::create(int fails, int time)
|
|
284
301
|
}
|
285
302
|
|
286
303
|
}
|
287
|
-
|
288
|
-
|
289
|
-
|
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 constrain(MSpace* s);
|
65
|
+
|
64
66
|
Gecode::MIntVarArray *intVarArray(const char *name ) const;
|
65
67
|
Gecode::MBoolVarArray *boolVarArray(const char *name ) const;
|
66
68
|
Gecode::MSetVarArray *setVarArray(const char *name) const;
|
@@ -80,6 +82,12 @@ class MDFS : public Gecode::Search::DFS
|
|
80
82
|
MDFS(MSpace *space, unsigned int c_d, unsigned int a_d, Search::Stop* st = 0);
|
81
83
|
~MDFS();
|
82
84
|
};
|
85
|
+
class MBAB : public Gecode::BAB<MSpace>
|
86
|
+
{
|
87
|
+
public:
|
88
|
+
MBAB(MSpace* space, unsigned int c_d, unsigned int a_d, Search::Stop* st = 0);
|
89
|
+
~MBAB();
|
90
|
+
};
|
83
91
|
|
84
92
|
namespace Search {
|
85
93
|
class MStop : public Gecode::Search::Stop
|
data/lib/gecoder/bindings.rb
CHANGED
@@ -1,7 +1,34 @@
|
|
1
1
|
require 'gecode.so'
|
2
2
|
module Gecode
|
3
|
-
# The
|
4
|
-
#
|
5
|
-
|
3
|
+
# The Gecode::Raw module is what the interface should use to access methods
|
4
|
+
# in Gecode. The actual bindings are located in ::GecodeRaw.
|
5
|
+
|
6
|
+
# We just make Gecode::Raw an alias of the real module.
|
6
7
|
Raw = ::GecodeRaw
|
8
|
+
# Log all calls via Gecode::Raw.
|
9
|
+
#Raw = ::LoggingLayer
|
10
|
+
|
11
|
+
# Describes a layer that delegates to GecodeRaw only after having logged the
|
12
|
+
# call.
|
13
|
+
module LoggingLayer
|
14
|
+
require 'logger'
|
15
|
+
|
16
|
+
def self.method_missing(name, *args)
|
17
|
+
logger.info{ "#{name}(#{args.join(', ')})" }
|
18
|
+
::GecodeRaw.send(name, *args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.const_missing(name)
|
22
|
+
::GecodeRaw.const_get(name)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Gets the logger, or creates one if none exists.
|
26
|
+
def self.logger
|
27
|
+
return @logger unless @logger.nil?
|
28
|
+
file = open('gecoder.log', File::WRONLY | File::APPEND | File::CREAT)
|
29
|
+
@logger = ::Logger.new(file)
|
30
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
31
|
+
@logger
|
32
|
+
end
|
33
|
+
end
|
7
34
|
end
|
@@ -293,6 +293,10 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
293
293
|
|
294
294
|
klass.add_method "debug"
|
295
295
|
|
296
|
+
klass.add_method "constrain" do |method|
|
297
|
+
method.add_parameter "Gecode::MSpace*", "s"
|
298
|
+
end
|
299
|
+
|
296
300
|
klass.add_method "own" do |method|
|
297
301
|
method.add_parameter "Gecode::MIntVarArray *", "x"
|
298
302
|
method.add_parameter "char*", "name"
|
@@ -390,6 +394,11 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
390
394
|
method.add_parameter "int", "max"
|
391
395
|
end
|
392
396
|
|
397
|
+
klass.add_constructor do |method|
|
398
|
+
method.add_parameter "Gecode::MSpace*", "home"
|
399
|
+
method.add_parameter "Gecode::IntSet", "s"
|
400
|
+
end
|
401
|
+
|
393
402
|
klass.add_method "max", "int"
|
394
403
|
|
395
404
|
klass.add_method "min", "int"
|
@@ -547,6 +556,19 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
|
|
547
556
|
klass.add_method "statistics", "Gecode::Search::Statistics"
|
548
557
|
end
|
549
558
|
|
559
|
+
ns.add_cxx_class "MBAB" do |klass|
|
560
|
+
klass.bindname = "BAB"
|
561
|
+
klass.add_constructor do |method|
|
562
|
+
method.add_parameter "Gecode::MSpace *", "s"
|
563
|
+
method.add_parameter "int", "c_d"
|
564
|
+
method.add_parameter "int", "a_d"
|
565
|
+
method.add_parameter "Gecode::Search::MStop *", "st"
|
566
|
+
end
|
567
|
+
|
568
|
+
klass.add_method "next", "Gecode::MSpace *"
|
569
|
+
klass.add_method "statistics", "Gecode::Search::Statistics"
|
570
|
+
end
|
571
|
+
|
550
572
|
# SEARCH NAMESPACE
|
551
573
|
|
552
574
|
ns.add_namespace "Search" do |searchns|
|
@@ -6,120 +6,83 @@
|
|
6
6
|
#
|
7
7
|
# This layer should be moved to the C++ side instead when possible for better
|
8
8
|
# performance.
|
9
|
-
module
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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 bool_var.
|
25
|
-
def new_bool_vars(count = 1)
|
26
|
-
bool_var_store.new_vars(count)
|
27
|
-
end
|
28
|
-
|
29
|
-
# Gets the bool variable with the specified index, nil if none exists.
|
30
|
-
def bool_var(index)
|
31
|
-
bool_var_store[index]
|
32
|
-
end
|
33
|
-
|
34
|
-
# Creates the specified number of set variables in the space with the
|
35
|
-
# specified domain for greatest lower bound and least upper bound
|
36
|
-
# (specified as either a range or enum). A range for the allowed
|
37
|
-
# cardinality of the set can also be specified, if none is specified, or
|
38
|
-
# nil is given, then the default range (anything) will be used. Returns
|
39
|
-
# the indices with which they can then be accessed using set_var.
|
40
|
-
def new_set_vars(*vars)
|
41
|
-
set_var_store.new_vars(*vars)
|
42
|
-
end
|
43
|
-
|
44
|
-
# Gets the set variable with the specified index, nil if none exists.
|
45
|
-
def set_var(index)
|
46
|
-
set_var_store[index]
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
# Retrieves the store used for integer variables. Creates one if none
|
52
|
-
# exists.
|
53
|
-
def int_var_store
|
54
|
-
if @int_var_store.nil?
|
55
|
-
@int_var_store = Gecode::Util::IntVarStore.new(self)
|
56
|
-
end
|
57
|
-
return @int_var_store
|
58
|
-
end
|
59
|
-
|
60
|
-
# Retrieves the store used for boolean variables. Creates one if none
|
61
|
-
# exists.
|
62
|
-
def bool_var_store
|
63
|
-
if @bool_var_store.nil?
|
64
|
-
@bool_var_store = Gecode::Util::BoolVarStore.new(self)
|
65
|
-
end
|
66
|
-
return @bool_var_store
|
67
|
-
end
|
68
|
-
|
69
|
-
# Retrieves the store used for set variables. Creates one if none exists.
|
70
|
-
def set_var_store
|
71
|
-
if @set_var_store.nil?
|
72
|
-
@set_var_store = Gecode::Util::SetVarStore.new(self)
|
73
|
-
end
|
74
|
-
return @set_var_store
|
75
|
-
end
|
9
|
+
module GecodeRaw
|
10
|
+
class Space
|
11
|
+
# Creates the specified number of integer variables in the space with the
|
12
|
+
# specified domain. Returns the indices with which they can then be
|
13
|
+
# accessed using int_var. The domain can be given as a Range (trated
|
14
|
+
# specially) or as another enum.
|
15
|
+
def new_int_vars(domain, count = 1)
|
16
|
+
int_var_store.new_vars(domain, count)
|
76
17
|
end
|
77
18
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
alias_method :in?, :in
|
82
|
-
alias_method :include?, :in
|
83
|
-
alias_method :range?, :range
|
19
|
+
# Gets the int variable with the specified index, nil if none exists.
|
20
|
+
def int_var(index)
|
21
|
+
int_var_store[index]
|
84
22
|
end
|
85
23
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
24
|
+
# Creates the specified number of boolean variables in the space. Returns
|
25
|
+
# the indices with which they can then be accessed using bool_var.
|
26
|
+
def new_bool_vars(count = 1)
|
27
|
+
bool_var_store.new_vars(count)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Gets the bool variable with the specified index, nil if none exists.
|
31
|
+
def bool_var(index)
|
32
|
+
bool_var_store[index]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Creates the specified number of set variables in the space with the
|
36
|
+
# specified domain for greatest lower bound and least upper bound
|
37
|
+
# (specified as either a range or enum). A range for the allowed
|
38
|
+
# cardinality of the set can also be specified, if none is specified, or
|
39
|
+
# nil is given, then the default range (anything) will be used. Returns
|
40
|
+
# the indices with which they can then be accessed using set_var.
|
41
|
+
def new_set_vars(*vars)
|
42
|
+
set_var_store.new_vars(*vars)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Gets the set variable with the specified index, nil if none exists.
|
46
|
+
def set_var(index)
|
47
|
+
set_var_store[index]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Used by Gecode during BAB-search.
|
51
|
+
def constrain(best_so_far_space)
|
52
|
+
Gecode::Model.constrain(self, best_so_far_space)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# Retrieves the store used for integer variables. Creates one if none
|
58
|
+
# exists.
|
59
|
+
def int_var_store
|
60
|
+
if @int_var_store.nil?
|
61
|
+
@int_var_store = Gecode::Util::IntVarStore.new(self)
|
92
62
|
end
|
93
|
-
|
94
|
-
|
95
|
-
|
63
|
+
return @int_var_store
|
64
|
+
end
|
65
|
+
|
66
|
+
# Retrieves the store used for boolean variables. Creates one if none
|
67
|
+
# exists.
|
68
|
+
def bool_var_store
|
69
|
+
if @bool_var_store.nil?
|
70
|
+
@bool_var_store = Gecode::Util::BoolVarStore.new(self)
|
96
71
|
end
|
72
|
+
return @bool_var_store
|
97
73
|
end
|
98
74
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
alias_method :include_glb?, :contains
|
104
|
-
alias_method :include?, :contains
|
105
|
-
def include_lub?(element)
|
106
|
-
!notContains(element)
|
75
|
+
# Retrieves the store used for set variables. Creates one if none exists.
|
76
|
+
def set_var_store
|
77
|
+
if @set_var_store.nil?
|
78
|
+
@set_var_store = Gecode::Util::SetVarStore.new(self)
|
107
79
|
end
|
108
|
-
|
109
|
-
alias_method :glb_min, :glbMin
|
110
|
-
alias_method :glb_max, :glbMax
|
111
|
-
alias_method :lub_min, :lubMin
|
112
|
-
alias_method :lub_max, :lubMax
|
113
|
-
|
114
|
-
alias_method :glb_size, :glbSize
|
115
|
-
alias_method :val_size, :glbSize
|
116
|
-
alias_method :lub_size, :lubSize
|
117
|
-
|
118
|
-
alias_method :card_min, :cardMin
|
119
|
-
alias_method :card_max, :cardMax
|
80
|
+
return @set_var_store
|
120
81
|
end
|
121
82
|
end
|
122
|
-
|
83
|
+
end
|
84
|
+
|
85
|
+
module Gecode
|
123
86
|
# Various utility (mainly used to change the behavior of the raw bindings).
|
124
87
|
module Util
|
125
88
|
# Provides common methods to the variable stores. The stores must provide
|
@@ -179,13 +142,24 @@ module Gecode
|
|
179
142
|
@next_index = @size
|
180
143
|
end
|
181
144
|
|
182
|
-
# Creates the specified number of
|
183
|
-
#
|
184
|
-
|
145
|
+
# Creates the specified number of integer variables in the space with the
|
146
|
+
# specified domain. Returns the indices with which they can then be
|
147
|
+
# accessed using int_var. The domain can be given as a Range (trated
|
148
|
+
# specially) or as another enum.
|
149
|
+
def new_vars(domain, count = 1)
|
185
150
|
grow(@next_index + count) # See the design note for more information.
|
186
151
|
count.times do |i|
|
152
|
+
if domain.kind_of? Range
|
153
|
+
domain_params = [domain.first, domain.last]
|
154
|
+
elsif domain.kind_of? Enumerable
|
155
|
+
arr = domain.to_a
|
156
|
+
domain_params = [Gecode::Raw::IntSet.new(arr, arr.size)]
|
157
|
+
else
|
158
|
+
raise TypeError, "Expected Enumerable, got #{domain.class}."
|
159
|
+
end
|
160
|
+
|
187
161
|
@var_array[@next_index] = Gecode::Raw::IntVar.new(@space,
|
188
|
-
|
162
|
+
*domain_params)
|
189
163
|
@next_index += 1
|
190
164
|
end
|
191
165
|
|
@@ -2,9 +2,9 @@ module Gecode
|
|
2
2
|
class Model
|
3
3
|
private
|
4
4
|
|
5
|
-
# Maps the names of the supported variable branch strategies
|
6
|
-
# corresponding constant in Gecode.
|
7
|
-
|
5
|
+
# Maps the names of the supported variable branch strategies for integer and
|
6
|
+
# booleans to the corresponding constant in Gecode.
|
7
|
+
BRANCH_INT_VAR_CONSTANTS = {
|
8
8
|
:none => Gecode::Raw::BVAR_NONE,
|
9
9
|
:smallest_min => Gecode::Raw::BVAR_MIN_MIN,
|
10
10
|
:largest_min => Gecode::Raw::BVAR_MIN_MAX,
|
@@ -19,16 +19,31 @@ module Gecode
|
|
19
19
|
:smallest_max_regret => Gecode::Raw::BVAR_REGRET_MAX_MIN,
|
20
20
|
:largest_max_regret => Gecode::Raw::BVAR_REGRET_MAX_MAX
|
21
21
|
}
|
22
|
+
# Maps the names of the supported variable branch strategies for sets to
|
23
|
+
# the corresponding constant in Gecode.
|
24
|
+
BRANCH_SET_VAR_CONSTANTS = {
|
25
|
+
:none => Gecode::Raw::SETBVAR_NONE,
|
26
|
+
:smallest_cardinality => Gecode::Raw::SETBVAR_MIN_CARD,
|
27
|
+
:largest_cardinality => Gecode::Raw::SETBVAR_MAX_CARD,
|
28
|
+
:smallest_unknown => Gecode::Raw::SETBVAR_MIN_UNKNOWN_ELEM,
|
29
|
+
:largest_unknown => Gecode::Raw::SETBVAR_MAX_UNKNOWN_ELEM
|
30
|
+
}
|
22
31
|
|
23
|
-
# Maps the names of the supported value branch strategies
|
24
|
-
# corresponding constant in Gecode.
|
25
|
-
|
32
|
+
# Maps the names of the supported value branch strategies for integers and
|
33
|
+
# booleans to the corresponding constant in Gecode.
|
34
|
+
BRANCH_INT_VALUE_CONSTANTS = {
|
26
35
|
:min => Gecode::Raw::BVAL_MIN,
|
27
36
|
:med => Gecode::Raw::BVAL_MED,
|
28
37
|
:max => Gecode::Raw::BVAL_MAX,
|
29
38
|
:split_min => Gecode::Raw::BVAL_SPLIT_MIN,
|
30
39
|
:split_max => Gecode::Raw::BVAL_SPLIT_MAX
|
31
40
|
}
|
41
|
+
# Maps the names of the supported value branch strategies for sets to the
|
42
|
+
# corresponding constant in Gecode.
|
43
|
+
BRANCH_SET_VALUE_CONSTANTS = {
|
44
|
+
:min => Gecode::Raw::SETBVAL_MIN,
|
45
|
+
:max => Gecode::Raw::SETBVAL_MAX
|
46
|
+
}
|
32
47
|
|
33
48
|
public
|
34
49
|
|
@@ -38,7 +53,8 @@ module Gecode
|
|
38
53
|
# used with the :value option. If nothing is specified then :variable uses
|
39
54
|
# :none and value uses :min.
|
40
55
|
#
|
41
|
-
# The following values can be used with :variable
|
56
|
+
# The following values can be used with :variable for integer and boolean
|
57
|
+
# enums:
|
42
58
|
# [:none] The first unassigned variable.
|
43
59
|
# [:smallest_min] The one with the smallest minimum.
|
44
60
|
# [:largest_min] The one with the largest minimum.
|
@@ -71,32 +87,67 @@ module Gecode
|
|
71
87
|
# the largest and second-largest value still in
|
72
88
|
# the domain.
|
73
89
|
#
|
74
|
-
# The following values can be used with :value
|
90
|
+
# The following values can be used with :value for integer and boolean
|
91
|
+
# enums:
|
75
92
|
# [:min] Selects the smallest value.
|
76
93
|
# [:med] Select the median value.
|
77
94
|
# [:max] Selects the largest vale
|
78
95
|
# [:split_min] Selects the lower half of the domain.
|
79
96
|
# [:split_max] Selects the upper half of the domain.
|
97
|
+
#
|
98
|
+
# The following values can be used with :variable for set enums:
|
99
|
+
# [:none] The first unassigned set.
|
100
|
+
# [:smallest_cardinality] The one with the smallest cardinality.
|
101
|
+
# [:largest_cardinality] The one with the largest cardinality.
|
102
|
+
# [:smallest_unknown] The one with the smallest number of unknown
|
103
|
+
# elements
|
104
|
+
# [:largest_unknown] The one with the largest number of unknown
|
105
|
+
# elements
|
106
|
+
#
|
107
|
+
# The following values can be used with :value set enums:
|
108
|
+
# enums:
|
109
|
+
# [:min] Selects the smallest value in the unknown part of the set.
|
110
|
+
# [:max] Selects the largest value in the unknown part of the set.
|
80
111
|
def branch_on(variables, options = {})
|
112
|
+
if variables.respond_to? :to_int_var_array or
|
113
|
+
variables.respond_to? :to_bool_var_array
|
114
|
+
add_branch(variables, options, BRANCH_INT_VAR_CONSTANTS,
|
115
|
+
BRANCH_INT_VALUE_CONSTANTS)
|
116
|
+
elsif variables.respond_to? :to_set_var_array
|
117
|
+
add_branch(variables, options, BRANCH_SET_VAR_CONSTANTS,
|
118
|
+
BRANCH_SET_VALUE_CONSTANTS)
|
119
|
+
else
|
120
|
+
raise TypeError, "Unknown type of variable enum #{variables.class}."
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
# Adds a branching selection for the specified variable with the specified
|
127
|
+
# options. The hashes are used to decode the options into Gecode's
|
128
|
+
# constants.
|
129
|
+
def add_branch(variables, options, branch_var_hash, branch_value_hash)
|
81
130
|
# Extract optional arguments.
|
82
131
|
var_strat = options.delete(:variable) || :none
|
83
132
|
val_strat = options.delete(:value) || :min
|
84
|
-
|
133
|
+
|
85
134
|
# Check that the options are correct.
|
86
135
|
unless options.empty?
|
87
136
|
raise ArgumentError, 'Unknown branching option given: ' +
|
88
137
|
options.keys.join(', ')
|
89
138
|
end
|
90
|
-
unless
|
139
|
+
unless branch_var_hash.include? var_strat
|
91
140
|
raise ArgumentError, "Unknown variable selection strategy: #{var_strat}"
|
92
141
|
end
|
93
|
-
unless
|
142
|
+
unless branch_value_hash.include? val_strat
|
94
143
|
raise ArgumentError, "Unknown value selection strategy: #{val_strat}"
|
95
144
|
end
|
96
145
|
|
97
|
-
# Add the branching.
|
98
|
-
|
99
|
-
|
146
|
+
# Add the branching as a gecode interaction.
|
147
|
+
add_interaction do
|
148
|
+
Gecode::Raw.branch(active_space, variables.to_var_array,
|
149
|
+
branch_var_hash[var_strat], branch_value_hash[val_strat])
|
150
|
+
end
|
100
151
|
end
|
101
152
|
end
|
102
153
|
end
|