gecoder 0.2.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/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
|