gecoder 0.5.0 → 0.6.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 +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
|