gecoder 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +17 -0
- data/LGPL-LICENSE +458 -0
- data/README +20 -0
- data/Rakefile +6 -0
- data/ext/extconf.rb +29 -0
- data/ext/missing.cpp +295 -0
- data/ext/missing.h +116 -0
- data/ext/vararray.cpp +312 -0
- data/ext/vararray.h +146 -0
- data/lib/gecoder.rb +4 -0
- data/lib/gecoder/bindings.rb +7 -0
- data/lib/gecoder/bindings/bindings.rb +2055 -0
- data/lib/gecoder/interface.rb +6 -0
- data/lib/gecoder/interface/binding_changes.rb +111 -0
- data/lib/gecoder/interface/branch.rb +102 -0
- data/lib/gecoder/interface/constraints.rb +10 -0
- data/lib/gecoder/interface/constraints/distinct.rb +15 -0
- data/lib/gecoder/interface/constraints/linear.rb +158 -0
- data/lib/gecoder/interface/constraints/relation.rb +76 -0
- data/lib/gecoder/interface/enum_wrapper.rb +64 -0
- data/lib/gecoder/interface/model.rb +130 -0
- data/lib/gecoder/interface/search.rb +23 -0
- data/vendor/rust/README +28 -0
- data/vendor/rust/bin/cxxgenerator.rb +93 -0
- data/vendor/rust/include/rust_checks.hh +115 -0
- data/vendor/rust/include/rust_conversions.hh +103 -0
- data/vendor/rust/rust.rb +67 -0
- data/vendor/rust/rust/attribute.rb +51 -0
- data/vendor/rust/rust/bindings.rb +172 -0
- data/vendor/rust/rust/class.rb +334 -0
- data/vendor/rust/rust/constants.rb +48 -0
- data/vendor/rust/rust/container.rb +110 -0
- data/vendor/rust/rust/cppifaceparser.rb +129 -0
- data/vendor/rust/rust/cwrapper.rb +72 -0
- data/vendor/rust/rust/cxxclass.rb +98 -0
- data/vendor/rust/rust/element.rb +81 -0
- data/vendor/rust/rust/enum.rb +63 -0
- data/vendor/rust/rust/function.rb +407 -0
- data/vendor/rust/rust/namespace.rb +61 -0
- data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
- data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
- data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
- data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
- data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
- data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
- data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
- data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +91 -0
- data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
- data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +12 -0
- data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
- data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
- data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
- data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
- data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
- data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
- data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
- data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +5 -0
- data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
- data/vendor/rust/rust/type.rb +98 -0
- data/vendor/rust/test/Makefile +4 -0
- data/vendor/rust/test/constants.rb +35 -0
- data/vendor/rust/test/cppclass.cc +40 -0
- data/vendor/rust/test/cppclass.hh +63 -0
- data/vendor/rust/test/cppclass.rb +59 -0
- data/vendor/rust/test/cwrapper.c +74 -0
- data/vendor/rust/test/cwrapper.h +41 -0
- data/vendor/rust/test/cwrapper.rb +56 -0
- data/vendor/rust/test/dummyclass.hh +31 -0
- data/vendor/rust/test/lib/extension-test.rb +98 -0
- data/vendor/rust/test/test-constants.rb +43 -0
- data/vendor/rust/test/test-cppclass.rb +82 -0
- data/vendor/rust/test/test-cwrapper.rb +77 -0
- metadata +144 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
# This file adds a small layer on top of the bindings. It alters the allocation
|
2
|
+
# of variables so that a single array is allocated in each space which is then
|
3
|
+
# used to store variable. The variables themselves are not directly returned,
|
4
|
+
# rather they are represented as the index in that store, which allows the
|
5
|
+
# variable to be retrieved back given a space.
|
6
|
+
#
|
7
|
+
# This layer should be moved to the C++ side instead when possible for better
|
8
|
+
# performance.
|
9
|
+
module Gecode::Raw
|
10
|
+
class Space
|
11
|
+
# Creates the specified number of integer variables in the store. Returns
|
12
|
+
# the indices with which they can then be accessed using int_var.
|
13
|
+
def new_int_vars(min, max, count = 1)
|
14
|
+
int_var_store.new_vars(min, max, count)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Gets the int variable with the specified index, nil if none exists.
|
18
|
+
def int_var(index)
|
19
|
+
int_var_store[index]
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# Retrieves the store used for integer variables. Creates one if none
|
25
|
+
# exists.
|
26
|
+
def int_var_store
|
27
|
+
if @int_var_store.nil?
|
28
|
+
@int_var_store = Gecode::Raw::IntVarStore.new(self)
|
29
|
+
end
|
30
|
+
return @int_var_store
|
31
|
+
end
|
32
|
+
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
|
+
|
46
|
+
# A string that identifies the array used by the store.
|
47
|
+
ARRAY_IDENTIFIER = 'int_array'
|
48
|
+
|
49
|
+
public
|
50
|
+
|
51
|
+
# Creates a store for the specified space with the specified capacit.
|
52
|
+
def initialize(space)
|
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
|
64
|
+
|
65
|
+
# Creates the specified number of new int variables with the specified
|
66
|
+
# range as domain. Returns the indices of the created variables as an array.
|
67
|
+
def new_vars(min, max, count = 1)
|
68
|
+
grow(@next_index + count) # See the design note for more information.
|
69
|
+
count.times do |i|
|
70
|
+
@var_array[@next_index] = Gecode::Raw::IntVar.new(@space,
|
71
|
+
min, max)
|
72
|
+
@next_index += 1
|
73
|
+
end
|
74
|
+
|
75
|
+
((@next_index - count)...@next_index).to_a
|
76
|
+
end
|
77
|
+
|
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
|
+
if new_size <= @size
|
91
|
+
raise ArgumentError, 'New size must be larger than the old one.'
|
92
|
+
end
|
93
|
+
|
94
|
+
new_array = Gecode::Raw::IntVarArray.new(@space, new_size)
|
95
|
+
@var_array.size.times do |i|
|
96
|
+
new_array[i] = @var_array[i]
|
97
|
+
end
|
98
|
+
@space.own(new_array, ARRAY_IDENTIFIER)
|
99
|
+
@var_array = new_array
|
100
|
+
@size = new_size
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class IntVar
|
105
|
+
# Aliases to make method-names more ruby-like.
|
106
|
+
alias_method :assigned?, :assigned
|
107
|
+
alias_method :in?, :in
|
108
|
+
alias_method :range?, :range
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Gecode
|
2
|
+
class Model
|
3
|
+
private
|
4
|
+
|
5
|
+
# Maps the names of the supported variable branch strategies to the
|
6
|
+
# corresponding constant in Gecode.
|
7
|
+
BRANCH_VAR_CONSTANTS = {
|
8
|
+
:none => Gecode::Raw::BVAR_NONE,
|
9
|
+
:smallest_min => Gecode::Raw::BVAR_MIN_MIN,
|
10
|
+
:largest_min => Gecode::Raw::BVAR_MIN_MAX,
|
11
|
+
:smallest_max => Gecode::Raw::BVAR_MAX_MIN,
|
12
|
+
:largest_max => Gecode::Raw::BVAR_MAX_MAX,
|
13
|
+
:smallest_size => Gecode::Raw::BVAR_SIZE_MIN,
|
14
|
+
:largest_size => Gecode::Raw::BVAR_SIZE_MAX,
|
15
|
+
:smallest_degree => Gecode::Raw::BVAR_DEGREE_MIN,
|
16
|
+
:largest_degree => Gecode::Raw::BVAR_DEGREE_MAX,
|
17
|
+
:smallest_min_regret => Gecode::Raw::BVAR_REGRET_MIN_MIN,
|
18
|
+
:largest_min_regret => Gecode::Raw::BVAR_REGRET_MIN_MAX,
|
19
|
+
:smallest_max_regret => Gecode::Raw::BVAR_REGRET_MAX_MIN,
|
20
|
+
:largest_max_regret => Gecode::Raw::BVAR_REGRET_MAX_MAX
|
21
|
+
}
|
22
|
+
|
23
|
+
# Maps the names of the supported value branch strategies to the
|
24
|
+
# corresponding constant in Gecode.
|
25
|
+
BRANCH_VALUE_CONSTANTS = {
|
26
|
+
:min => Gecode::Raw::BVAL_MIN,
|
27
|
+
:med => Gecode::Raw::BVAL_MED,
|
28
|
+
:max => Gecode::Raw::BVAL_MAX,
|
29
|
+
:split_min => Gecode::Raw::BVAL_SPLIT_MIN,
|
30
|
+
:split_max => Gecode::Raw::BVAL_SPLIT_MAX
|
31
|
+
}
|
32
|
+
|
33
|
+
public
|
34
|
+
|
35
|
+
# Specifies which variables that should be branched on. One can optionally
|
36
|
+
# also select which of the variables that should be used first with the
|
37
|
+
# :variable option and which value in that variable's domain that should be
|
38
|
+
# used with the :value option. If nothing is specified then :variable uses
|
39
|
+
# :none and value uses :min.
|
40
|
+
#
|
41
|
+
# The following values can be used with :variable
|
42
|
+
# [:none] The first unassigned variable.
|
43
|
+
# [:smallest_min] The one with the smallest minimum.
|
44
|
+
# [:largest_min] The one with the largest minimum.
|
45
|
+
# [:smallest_max] The one with the smallest maximum.
|
46
|
+
# [:largest_max] The one with the largest maximum.
|
47
|
+
# [:smallest_size] The one with the smallest size.
|
48
|
+
# [:largest_size] The one with the larges size.
|
49
|
+
# [:smallest_degree] The one with the smallest degree. The degree of a
|
50
|
+
# variable is defined as the number of dependant
|
51
|
+
# propagators. In case of ties, choose the variable
|
52
|
+
# with smallest domain.
|
53
|
+
# [:largest_degree] The one with the largest degree. The degree of a
|
54
|
+
# variable is defined as the number of dependant
|
55
|
+
# propagators. In case of ties, choose the variable
|
56
|
+
# with smallest domain.
|
57
|
+
# [:smallest_min_regret] The one with the smallest min-regret. The
|
58
|
+
# min-regret of a variable is the difference between
|
59
|
+
# the smallest and second-smallest value still in
|
60
|
+
# the domain.
|
61
|
+
# [:largest_min_regret] The one with the largest min-regret. The
|
62
|
+
# min-regret of a variable is the difference between
|
63
|
+
# the smallest and second-smallest value still in
|
64
|
+
# the domain.
|
65
|
+
# [:smallest_max_regret] The one with the smallest max-regret The
|
66
|
+
# max-regret of a variable is the difference between
|
67
|
+
# the largest and second-largest value still in
|
68
|
+
# the domain.
|
69
|
+
# [:largest_max_regret] The one with the largest max-regret. The
|
70
|
+
# max-regret of a variable is the difference between
|
71
|
+
# the largest and second-largest value still in
|
72
|
+
# the domain.
|
73
|
+
#
|
74
|
+
# The following values can be used with :value
|
75
|
+
# [:min] Selects the smallest value.
|
76
|
+
# [:med] Select the median value.
|
77
|
+
# [:max] Selects the largest vale
|
78
|
+
# [:split_min] Selects the lower half of the domain.
|
79
|
+
# [:split_max] Selects the upper half of the domain.
|
80
|
+
def branch_on(variables, options = {})
|
81
|
+
# Extract optional arguments.
|
82
|
+
var_strat = options.delete(:variable) || :none
|
83
|
+
val_strat = options.delete(:value) || :min
|
84
|
+
|
85
|
+
# Check that the options are correct.
|
86
|
+
unless options.empty?
|
87
|
+
raise ArgumentError, 'Unknown branching option given: ' +
|
88
|
+
options.keys.join(', ')
|
89
|
+
end
|
90
|
+
unless BRANCH_VAR_CONSTANTS.include? var_strat
|
91
|
+
raise ArgumentError, "Unknown variable selection strategy: #{var_strat}"
|
92
|
+
end
|
93
|
+
unless BRANCH_VALUE_CONSTANTS.include? val_strat
|
94
|
+
raise ArgumentError, "Unknown value selection strategy: #{val_strat}"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Add the branching.
|
98
|
+
Gecode::Raw.branch(active_space, variables.to_int_var_array,
|
99
|
+
BRANCH_VAR_CONSTANTS[var_strat], BRANCH_VALUE_CONSTANTS[val_strat])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'gecoder/interface/constraints/relation'
|
2
|
+
require 'gecoder/interface/constraints/distinct'
|
3
|
+
require 'gecoder/interface/constraints/linear'
|
4
|
+
|
5
|
+
module Gecode
|
6
|
+
# An error signaling that the constraint specified is missing (e.g. one tried
|
7
|
+
# to negate a constraint, but no negated form is implemented).
|
8
|
+
class MissingConstraintError < StandardError
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Gecode
|
2
|
+
class IntVarEnumConstraintExpression
|
3
|
+
# Posts a distinct constraint on the variables in the enum.
|
4
|
+
def distinct
|
5
|
+
if @negate
|
6
|
+
# The best we could implement it as from here would be a bunch of
|
7
|
+
# reified pairwise equality constraints.
|
8
|
+
raise Gecode::MissingConstraintError, 'A negated distinct has not ' +
|
9
|
+
'been implemented.'
|
10
|
+
end
|
11
|
+
|
12
|
+
Gecode::Raw::distinct(@space, @var_array, Gecode::Raw::ICL_DEF)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
module Gecode
|
2
|
+
class FreeIntVar
|
3
|
+
# Creates a linear expression where the int variables are summed.
|
4
|
+
def +(var)
|
5
|
+
Gecode::LinearConstraintExpressionNode.new(self, active_space) + var
|
6
|
+
end
|
7
|
+
|
8
|
+
# Creates a linear expression where the int variable is multiplied with
|
9
|
+
# a constant integer.
|
10
|
+
def *(int)
|
11
|
+
Gecode::LinearConstraintExpressionNode.new(self, active_space) * int
|
12
|
+
end
|
13
|
+
|
14
|
+
# Creates a linear expression where the specified variable is subtracted
|
15
|
+
# from this one.
|
16
|
+
def -(var)
|
17
|
+
Gecode::LinearConstraintExpressionNode.new(self, active_space) - var
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module LinearConstraintHelper
|
22
|
+
OPERATION_TYPES = [:+, :-, :*]
|
23
|
+
|
24
|
+
# Define methods for the available operations.
|
25
|
+
OPERATION_TYPES.each do |name|
|
26
|
+
module_eval <<-"end_code"
|
27
|
+
def #{name}(expression)
|
28
|
+
unless expression.kind_of? Gecode::LinearConstraintExpressionTree
|
29
|
+
expression = Gecode::LinearConstraintExpressionNode.new(expression)
|
30
|
+
end
|
31
|
+
Gecode::LinearConstraintExpressionTree.new(self, expression, :#{name})
|
32
|
+
end
|
33
|
+
end_code
|
34
|
+
end
|
35
|
+
|
36
|
+
# Specifies that a constraint must hold for the linear expression.
|
37
|
+
def must
|
38
|
+
Gecode::LinearConstraintExpression.new(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Specifies that the negation of a constraint must hold for the linear
|
42
|
+
# expression.
|
43
|
+
def must_not
|
44
|
+
Gecode::LinearConstraintExpression.new(self, true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Describes a linear constraint that starts with a linear expression followed
|
49
|
+
# by must or must_not.
|
50
|
+
class LinearConstraintExpressionTree
|
51
|
+
include Gecode::LinearConstraintHelper
|
52
|
+
|
53
|
+
# Constructs a new expression with the specified variable
|
54
|
+
def initialize(left_node, right_node, operation)
|
55
|
+
@left = left_node
|
56
|
+
@right = right_node
|
57
|
+
@operation = operation
|
58
|
+
end
|
59
|
+
|
60
|
+
# Converts the linear expression to an instance of
|
61
|
+
# Gecode::Raw::MiniModel::LinExpr
|
62
|
+
def to_minimodel_lin_exp
|
63
|
+
@left.to_minimodel_lin_exp.send(@operation, @right.to_minimodel_lin_exp)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Fetches the space that the expression's variables is in.
|
67
|
+
def space
|
68
|
+
@left.space || @right.space
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Describes a single node in a linear constrain expression.
|
73
|
+
class LinearConstraintExpressionNode
|
74
|
+
include Gecode::LinearConstraintHelper
|
75
|
+
|
76
|
+
attr :space
|
77
|
+
|
78
|
+
def initialize(value, space = nil)
|
79
|
+
@value = value
|
80
|
+
@space = space
|
81
|
+
end
|
82
|
+
|
83
|
+
# Converts the linear expression to an instance of
|
84
|
+
# Gecode::Raw::MiniModel::LinExpr
|
85
|
+
def to_minimodel_lin_exp
|
86
|
+
expression = @value
|
87
|
+
if expression.kind_of? FreeIntVar
|
88
|
+
# Minimodel requires that we do this first.
|
89
|
+
expression = expression.bind * 1
|
90
|
+
end
|
91
|
+
expression
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Describes a linear constraint expression that starts with a linear
|
96
|
+
# expression followed by must or must_not.
|
97
|
+
class LinearConstraintExpression
|
98
|
+
# TODO: this is awfully similar to IntVarConstrainExpression. There should
|
99
|
+
# be some way to combine them.
|
100
|
+
|
101
|
+
# Maps the names of the methods to the corresponding integer relation
|
102
|
+
# type in Gecode.
|
103
|
+
RELATION_TYPES = {
|
104
|
+
:== => Gecode::Raw::IRT_EQ,
|
105
|
+
:<= => Gecode::Raw::IRT_LQ,
|
106
|
+
:< => Gecode::Raw::IRT_LE,
|
107
|
+
:>= => Gecode::Raw::IRT_GQ,
|
108
|
+
:> => Gecode::Raw::IRT_GR }
|
109
|
+
# The same as above, but negated.
|
110
|
+
NEGATED_RELATION_TYPES = {
|
111
|
+
:== => Gecode::Raw::IRT_NQ,
|
112
|
+
:<= => Gecode::Raw::IRT_GR,
|
113
|
+
:< => Gecode::Raw::IRT_GQ,
|
114
|
+
:>= => Gecode::Raw::IRT_LE,
|
115
|
+
:> => Gecode::Raw::IRT_LQ
|
116
|
+
}
|
117
|
+
|
118
|
+
# Constructs the expression with the specified left hand side. The
|
119
|
+
# expression can optionally be negated.
|
120
|
+
def initialize(left_hand_side, negate = false)
|
121
|
+
@lhs = left_hand_side
|
122
|
+
unless negate
|
123
|
+
@method_relations = RELATION_TYPES
|
124
|
+
else
|
125
|
+
@method_relations = NEGATED_RELATION_TYPES
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
RELATION_TYPES.each_key do |name|
|
130
|
+
module_eval <<-"end_code"
|
131
|
+
def #{name}(expression)
|
132
|
+
post_relation_constraint(@method_relations[:#{name}], expression)
|
133
|
+
end
|
134
|
+
end_code
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
# Places the relation constraint corresponding to the specified (integer)
|
140
|
+
# relation type (as specified by Gecode) in relation to the specifed
|
141
|
+
# element.
|
142
|
+
#
|
143
|
+
# Raises TypeError if the element is of a type that doesn't allow a relation
|
144
|
+
# to be specified.
|
145
|
+
def post_relation_constraint(relation_type, right_hand_side)
|
146
|
+
if right_hand_side.respond_to? :to_minimodel_lin_exp
|
147
|
+
right_hand_side = right_hand_side.to_minimodel_lin_exp
|
148
|
+
elsif right_hand_side.kind_of? Gecode::FreeIntVar
|
149
|
+
right_hand_side = right_hand_side.bind * 1
|
150
|
+
elsif not right_hand_side.kind_of? Fixnum
|
151
|
+
raise TypeError, 'Invalid right hand side of linear equation.'
|
152
|
+
end
|
153
|
+
|
154
|
+
(@lhs.to_minimodel_lin_exp - right_hand_side).post(@lhs.space,
|
155
|
+
relation_type, Gecode::Raw::ICL_DEF)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Gecode
|
2
|
+
class FreeIntVar
|
3
|
+
# Specifies that a constraint must hold for the integer variable.
|
4
|
+
def must
|
5
|
+
Gecode::IntVarConstraintExpression.new(active_space, self.bind)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Specifies that the negation of a constraint must hold for the integer
|
9
|
+
# variable.
|
10
|
+
def must_not
|
11
|
+
Gecode::IntVarConstraintExpression.new(active_space, self.bind, true)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Describes a constraint expression that starts with a single integer variable
|
16
|
+
# followed by must or must_not.
|
17
|
+
class IntVarConstraintExpression
|
18
|
+
private
|
19
|
+
|
20
|
+
# Maps the names of the methods to the corresponding integer relation
|
21
|
+
# type in Gecode.
|
22
|
+
RELATION_TYPES = {
|
23
|
+
:== => Gecode::Raw::IRT_EQ,
|
24
|
+
:<= => Gecode::Raw::IRT_LQ,
|
25
|
+
:< => Gecode::Raw::IRT_LE,
|
26
|
+
:>= => Gecode::Raw::IRT_GQ,
|
27
|
+
:> => Gecode::Raw::IRT_GR }
|
28
|
+
# The same as above, but negated.
|
29
|
+
NEGATED_RELATION_TYPES = {
|
30
|
+
:== => Gecode::Raw::IRT_NQ,
|
31
|
+
:<= => Gecode::Raw::IRT_GR,
|
32
|
+
:< => Gecode::Raw::IRT_GQ,
|
33
|
+
:>= => Gecode::Raw::IRT_LE,
|
34
|
+
:> => Gecode::Raw::IRT_LQ
|
35
|
+
}
|
36
|
+
|
37
|
+
public
|
38
|
+
|
39
|
+
# Constructs a new expression with the specified space and (bound) variable
|
40
|
+
# as source. The expression can optionally be negated.
|
41
|
+
def initialize(space, var, negate = false)
|
42
|
+
@space = space
|
43
|
+
@var = var
|
44
|
+
unless negate
|
45
|
+
@method_relations = RELATION_TYPES
|
46
|
+
else
|
47
|
+
@method_relations = NEGATED_RELATION_TYPES
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
RELATION_TYPES.each_key do |name|
|
52
|
+
module_eval <<-"end_code"
|
53
|
+
def #{name}(element)
|
54
|
+
post_relation_constraint(@method_relations[:#{name}], element)
|
55
|
+
end
|
56
|
+
end_code
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# Places the relation constraint corresponding to the specified (integer)
|
62
|
+
# relation type (as specified by Gecode) in relation to the specifed
|
63
|
+
# element.
|
64
|
+
#
|
65
|
+
# Raises TypeError if the element is of a type that doesn't allow a relation
|
66
|
+
# to be specified.
|
67
|
+
def post_relation_constraint(relation_type, element)
|
68
|
+
if element.kind_of? Fixnum
|
69
|
+
Gecode::Raw::rel(@space, @var, relation_type, element,
|
70
|
+
Gecode::Raw::ICL_DEF)
|
71
|
+
else
|
72
|
+
raise TypeError, 'Relations only allow Fixnum.'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|