gecoder 0.8.3 → 0.9.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 +15 -0
- data/README +6 -2
- data/example/equation_system.rb +15 -0
- data/example/magic_sequence.rb +7 -7
- data/example/money.rb +36 -0
- data/example/queens.rb +7 -8
- data/example/send_most_money.rb +1 -1
- data/example/square_tiling.rb +2 -2
- data/example/sudoku-set.rb +11 -12
- data/example/sudoku.rb +40 -45
- data/ext/extconf.rb +0 -0
- data/lib/gecoder/bindings.rb +42 -0
- data/lib/gecoder/bindings/bindings.rb +16 -0
- data/lib/gecoder/interface.rb +2 -1
- data/lib/gecoder/interface/branch.rb +16 -9
- data/lib/gecoder/interface/constraints.rb +410 -451
- data/lib/gecoder/interface/constraints/bool/boolean.rb +205 -213
- data/lib/gecoder/interface/constraints/bool/channel.rb +4 -5
- data/lib/gecoder/interface/constraints/bool/linear.rb +192 -21
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +43 -39
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +43 -49
- data/lib/gecoder/interface/constraints/bool_enum/relation.rb +38 -71
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +73 -22
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +140 -61
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +4 -4
- data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
- data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +131 -130
- data/lib/gecoder/interface/constraints/int/channel.rb +21 -31
- data/lib/gecoder/interface/constraints/int/domain.rb +45 -42
- data/lib/gecoder/interface/constraints/int/linear.rb +85 -239
- data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +55 -64
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +35 -37
- data/lib/gecoder/interface/constraints/int_enum/count.rb +53 -78
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +36 -46
- data/lib/gecoder/interface/constraints/int_enum/element.rb +39 -57
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +15 -19
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +65 -72
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +42 -45
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +79 -22
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +215 -44
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +14 -14
- data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
- data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +43 -53
- data/lib/gecoder/interface/constraints/set/channel.rb +26 -29
- data/lib/gecoder/interface/constraints/set/connection.rb +89 -152
- data/lib/gecoder/interface/constraints/set/domain.rb +112 -65
- data/lib/gecoder/interface/constraints/set/include.rb +36 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +96 -110
- data/lib/gecoder/interface/constraints/set/relation.rb +114 -137
- data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
- data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +23 -27
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +18 -19
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +62 -53
- data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +73 -23
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +222 -57
- data/lib/gecoder/interface/enum_matrix.rb +4 -4
- data/lib/gecoder/interface/enum_wrapper.rb +71 -22
- data/lib/gecoder/interface/model.rb +167 -12
- data/lib/gecoder/interface/model_sugar.rb +84 -0
- data/lib/gecoder/interface/search.rb +30 -18
- data/lib/gecoder/interface/variables.rb +103 -33
- data/lib/gecoder/version.rb +2 -2
- data/specs/bool_var.rb +19 -12
- data/specs/constraints/{boolean.rb → bool/boolean.rb} +103 -28
- data/specs/constraints/bool/boolean_properties.rb +51 -0
- data/specs/constraints/bool/linear.rb +213 -0
- data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
- data/specs/constraints/bool_enum/channel.rb +102 -0
- data/specs/constraints/{extensional.rb → bool_enum/extensional.rb} +32 -101
- data/specs/constraints/constraint_helper.rb +149 -179
- data/specs/constraints/constraint_receivers.rb +103 -0
- data/specs/constraints/constraints.rb +6 -63
- data/specs/constraints/fixnum_enum/element.rb +58 -0
- data/specs/constraints/fixnum_enum/operation.rb +67 -0
- data/specs/constraints/int/arithmetic.rb +149 -0
- data/specs/constraints/int/channel.rb +101 -0
- data/specs/constraints/int/domain.rb +106 -0
- data/specs/constraints/int/linear.rb +183 -0
- data/specs/constraints/int/linear_properties.rb +97 -0
- data/specs/constraints/int/relation.rb +84 -0
- data/specs/constraints/int_enum/arithmetic.rb +72 -0
- data/specs/constraints/int_enum/channel.rb +57 -0
- data/specs/constraints/int_enum/count.rb +72 -0
- data/specs/constraints/int_enum/distinct.rb +80 -0
- data/specs/constraints/int_enum/element.rb +61 -0
- data/specs/constraints/int_enum/equality.rb +29 -0
- data/specs/constraints/int_enum/extensional.rb +224 -0
- data/specs/constraints/int_enum/sort.rb +167 -0
- data/specs/constraints/operands.rb +264 -0
- data/specs/constraints/property_helper.rb +443 -0
- data/specs/constraints/reification_sugar.rb +4 -5
- data/specs/constraints/selected_set/select.rb +56 -0
- data/specs/constraints/selected_set/select_properties.rb +157 -0
- data/specs/constraints/set/cardinality.rb +58 -0
- data/specs/constraints/set/cardinality_properties.rb +46 -0
- data/specs/constraints/set/channel.rb +77 -0
- data/specs/constraints/set/connection.rb +176 -0
- data/specs/constraints/set/domain.rb +197 -0
- data/specs/constraints/set/include.rb +36 -0
- data/specs/constraints/set/operation.rb +132 -0
- data/specs/constraints/set/relation.rb +117 -0
- data/specs/constraints/set_elements/relation.rb +84 -0
- data/specs/constraints/set_enum/channel.rb +80 -0
- data/specs/constraints/set_enum/distinct.rb +59 -0
- data/specs/constraints/set_enum/operation.rb +111 -0
- data/specs/constraints/set_enum/select.rb +73 -0
- data/specs/enum_wrapper.rb +53 -3
- data/specs/int_var.rb +44 -25
- data/specs/model.rb +58 -1
- data/specs/model_sugar.rb +30 -0
- data/specs/search.rb +24 -5
- data/specs/selected_set.rb +39 -0
- data/specs/set_elements.rb +34 -0
- data/specs/set_var.rb +22 -8
- data/specs/spec_helper.rb +206 -6
- data/tasks/distribution.rake +22 -7
- data/tasks/svn.rake +3 -1
- metadata +218 -134
- data/lib/gecoder/interface/constraints/set_enum/selection.rb +0 -217
- data/specs/constraints/arithmetic.rb +0 -351
- data/specs/constraints/bool_enum_relation.rb +0 -160
- data/specs/constraints/cardinality.rb +0 -157
- data/specs/constraints/channel.rb +0 -454
- data/specs/constraints/connection.rb +0 -369
- data/specs/constraints/count.rb +0 -146
- data/specs/constraints/distinct.rb +0 -164
- data/specs/constraints/element.rb +0 -108
- data/specs/constraints/equality.rb +0 -31
- data/specs/constraints/int_domain.rb +0 -70
- data/specs/constraints/int_relation.rb +0 -82
- data/specs/constraints/linear.rb +0 -340
- data/specs/constraints/selection.rb +0 -292
- data/specs/constraints/set_domain.rb +0 -185
- data/specs/constraints/set_operation.rb +0 -285
- data/specs/constraints/set_relation.rb +0 -197
- data/specs/constraints/sort.rb +0 -179
@@ -1,217 +0,0 @@
|
|
1
|
-
module Gecode::SetEnumMethods
|
2
|
-
# This adds the adder for the methods in the modules including it. The
|
3
|
-
# reason for doing it so indirect is that the first #[] won't be defined
|
4
|
-
# before the module that this is mixed into is mixed into an enum.
|
5
|
-
def self.included(mod) #:nodoc:
|
6
|
-
mod.module_eval do
|
7
|
-
# Now we enter the module that the module possibly defining #[]
|
8
|
-
# is mixed into.
|
9
|
-
if instance_methods.include?('[]') and
|
10
|
-
not instance_methods.include?('pre_selection_access')
|
11
|
-
alias_method :pre_selection_access, :[]
|
12
|
-
end
|
13
|
-
|
14
|
-
def [](*vars)
|
15
|
-
# Hook in an element constraint if a variable is used for array
|
16
|
-
# access.
|
17
|
-
if vars.first.kind_of? Gecode::FreeIntVar
|
18
|
-
params = {:lhs => self, :index => vars.first}
|
19
|
-
Gecode::Constraints::SetEnum::Selection::SelectExpressionStub.new(
|
20
|
-
@model, params)
|
21
|
-
elsif vars.first.kind_of? Gecode::FreeSetVar
|
22
|
-
params = {:lhs => self, :indices => vars.first}
|
23
|
-
Gecode::Constraints::SetEnum::Selection::SetAccessStub.new(
|
24
|
-
@model, params)
|
25
|
-
else
|
26
|
-
pre_selection_access(*vars) if respond_to? :pre_selection_access
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# A module that gathers the classes and modules used by selection constraints.
|
34
|
-
module Gecode::Constraints::SetEnum::Selection #:nodoc:
|
35
|
-
# Describes an expression stub started with a set var enum followed with an
|
36
|
-
# array access using a set variable.
|
37
|
-
class SetAccessStub < Gecode::Constraints::ExpressionStub #:nodoc:
|
38
|
-
include Gecode::Constraints::LeftHandSideMethods
|
39
|
-
|
40
|
-
# Starts a union selection constraint on the selected sets.
|
41
|
-
def union
|
42
|
-
UnionExpressionStub.new(@model, @params)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Starts a intersection selection constraint on the selected sets. The
|
46
|
-
# option :with may optionally be specified, in which case the value should
|
47
|
-
# be an enumeration of the elements in the universe.
|
48
|
-
def intersection(options = {})
|
49
|
-
unless options.empty?
|
50
|
-
unless options.size == 1 and options.has_key?(:with)
|
51
|
-
raise ArgumentError, "Expected option key :with, got #{options.keys}."
|
52
|
-
else
|
53
|
-
universe = options[:with]
|
54
|
-
unless universe.kind_of?(Enumerable) and
|
55
|
-
universe.all?{ |element| element.kind_of? Fixnum }
|
56
|
-
raise TypeError, "Expected the universe to be specified as " +
|
57
|
-
"an enumeration of fixnum, got #{universe.class}."
|
58
|
-
end
|
59
|
-
@params.update(:universe => universe)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
IntersectionExpressionStub.new(@model, @params)
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
# Produces an expression with position for the lhs module.
|
69
|
-
def expression(params)
|
70
|
-
SetAccessExpression.new(@model, @params.update(params))
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Describes an expression that starts with an set variable enum followed with
|
75
|
-
# an array access using a set variable followed by some form of must.
|
76
|
-
class SetAccessExpression < Gecode::Constraints::Set::Expression #:nodoc:
|
77
|
-
# Constrains the selected sets to be disjoint.
|
78
|
-
def disjoint
|
79
|
-
if @params[:negate]
|
80
|
-
raise Gecode::MissingConstraintError, 'A negated set selection ' +
|
81
|
-
'disjoint is not implemented.'
|
82
|
-
end
|
83
|
-
|
84
|
-
@model.add_constraint DisjointConstraint.new(@model, @params)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# Describes a CompositeStub for the set select constraint, which constrains
|
89
|
-
# the set in a position specified by an integer variable in an enumeration of
|
90
|
-
# set variable.
|
91
|
-
#
|
92
|
-
# == Examples
|
93
|
-
#
|
94
|
-
# # The set at the position described by the integer variable
|
95
|
-
# # +singleton_zero_position+ in the enumeration +sets+ of set variables
|
96
|
-
# # must equal [0].
|
97
|
-
# sets[singleton_zero_position].must == 0
|
98
|
-
#
|
99
|
-
# # The set at the position described by the integer variable +position+ in
|
100
|
-
# # the enumeration +sets+ of set variables must be a subset of +set+.
|
101
|
-
# sets[position].must_be.subset_of set
|
102
|
-
#
|
103
|
-
# # The same as above, but reified with the boolean variable +bool+.
|
104
|
-
# sets[position].must_be.subset_of(set, :reify => bool)
|
105
|
-
class SelectExpressionStub < Gecode::Constraints::Set::CompositeStub
|
106
|
-
def constrain_equal(variable, params, constrain)
|
107
|
-
enum, index = @params.values_at(:lhs, :index)
|
108
|
-
if constrain
|
109
|
-
variable.must_be.subset_of enum.upper_bound_range
|
110
|
-
end
|
111
|
-
|
112
|
-
Gecode::Raw::selectSet(@model.active_space, enum.to_set_var_array,
|
113
|
-
index.bind, variable.bind)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# Describes a CompositeStub for the set union selection constraint,
|
118
|
-
# which constrains the union of sets located at the positions
|
119
|
-
# specified by a set variable in an enumeration of set variables.
|
120
|
-
#
|
121
|
-
# == Examples
|
122
|
-
#
|
123
|
-
# # The sets in the enumeration set variable +sets+ located at the positions
|
124
|
-
# # described by the set variable +selected_sets+ must have a union that's
|
125
|
-
# # a superset of [0,4,17].
|
126
|
-
# sets[selected_sets].union.must_be.superset_of [0,4,17]
|
127
|
-
#
|
128
|
-
# # The sets in the enumeration set variable +sets+ located at the positions
|
129
|
-
# # described by the set variable +selected_sets+ must have a union that's
|
130
|
-
# # disjoint with the set variable +set+.
|
131
|
-
# sets[selected_sets].union.must_be.disjoint_with set
|
132
|
-
#
|
133
|
-
# # The same as above but reified with the boolean variable
|
134
|
-
# # +union_is_disjoint+.
|
135
|
-
# sets[selected_sets].union.must_be.disjoint_with(set,
|
136
|
-
# :reify => union_is_disjoin)
|
137
|
-
class UnionExpressionStub < Gecode::Constraints::Set::CompositeStub
|
138
|
-
def constrain_equal(variable, params, constrain)
|
139
|
-
enum, indices = @params.values_at(:lhs, :indices)
|
140
|
-
if constrain
|
141
|
-
variable.must_be.subset_of enum.upper_bound_range
|
142
|
-
end
|
143
|
-
|
144
|
-
Gecode::Raw::selectUnion(@model.active_space, enum.to_set_var_array,
|
145
|
-
indices.bind, variable.bind)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
# Describes a CompositeStub for the set intersection selection constraint,
|
150
|
-
# which constrains the intersection of sets located at the positions
|
151
|
-
# specified by a set variable in an enumeration of set variables.
|
152
|
-
#
|
153
|
-
# Optionally a universe may also be specified.
|
154
|
-
#
|
155
|
-
# == Examples
|
156
|
-
#
|
157
|
-
# # The sets in the enumeration set variable +sets+ located at the positions
|
158
|
-
# # described by the set variable +selected_sets+ must have an intersection
|
159
|
-
# # that's a superset of [0,4,17].
|
160
|
-
# sets[selected_sets].intersection.must_be.superset_of [0,4,17]
|
161
|
-
#
|
162
|
-
# # The sets in the enumeration set variable +sets+ located at the positions
|
163
|
-
# # described by the set variable +selected_sets+ must have an intersection
|
164
|
-
# # that's disjoint with the set variable +set+.
|
165
|
-
# sets[selected_sets].intersection.must_be.disjoint_with set
|
166
|
-
#
|
167
|
-
# # The sets in the enumeration set variable +sets+ located at the positions
|
168
|
-
# # described by the set variable +selected_sets+ must have an intersection
|
169
|
-
# # that's disjoint with the set variable +set+ inside the universe 0..17.
|
170
|
-
# sets[selected_sets].intersection(:with => 0..17).must_be.disjoint_with set
|
171
|
-
#
|
172
|
-
# # The sets in the enumeration set variable +sets+ located at the positions
|
173
|
-
# # described by the set variable +selected_sets+ must have an intersection
|
174
|
-
# # that's disjoint with the set variable +set+ inside the universe
|
175
|
-
# # described by the set variable +universe+.
|
176
|
-
# sets[selected_sets].intersection(:with => universe).must_be.disjoint_with set
|
177
|
-
#
|
178
|
-
#
|
179
|
-
# # The same as above but reified with the boolean variable
|
180
|
-
# # +intersection_is_disjoint+.
|
181
|
-
# sets[selected_sets].intersection(:with => universe).must_be.disjoint_with(
|
182
|
-
# set, :reifty => intersection_is_disjoin)
|
183
|
-
class IntersectionExpressionStub < Gecode::Constraints::Set::CompositeStub
|
184
|
-
def constrain_equal(variable, params, constrain)
|
185
|
-
enum, indices, universe = @params.values_at(:lhs, :indices, :universe)
|
186
|
-
# We can't do any useful constraining here since the empty intersection
|
187
|
-
# is the universe.
|
188
|
-
|
189
|
-
if universe.nil?
|
190
|
-
Gecode::Raw::selectInter(@model.active_space, enum.to_set_var_array,
|
191
|
-
indices.bind, variable.bind)
|
192
|
-
else
|
193
|
-
Gecode::Raw::selectInterIn(@model.active_space, enum.to_set_var_array,
|
194
|
-
indices.bind, variable.bind,
|
195
|
-
Gecode::Constraints::Util.constant_set_to_int_set(universe))
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
# Describes a disjoint constraint, which constrains all set variable is an
|
201
|
-
# enumeration, at the position specified by a set variable, to be disjoint.
|
202
|
-
#
|
203
|
-
# Does not support negation nor reification.
|
204
|
-
#
|
205
|
-
# == Examples
|
206
|
-
#
|
207
|
-
# # The set variable located in the enumeration +sets+ at positions
|
208
|
-
# # described by +disjoint_set_positions+ must be disjoint.
|
209
|
-
# sets[disjoint_set_positions].must_be.disjoint
|
210
|
-
class DisjointConstraint < Gecode::Constraints::Constraint
|
211
|
-
def post
|
212
|
-
enum, indices = @params.values_at(:lhs, :indices)
|
213
|
-
Gecode::Raw.selectDisjoint(@model.active_space, enum.to_set_var_array,
|
214
|
-
indices.bind)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
@@ -1,351 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
require File.dirname(__FILE__) + '/constraint_helper'
|
3
|
-
|
4
|
-
class ArithmeticSampleProblem < Gecode::Model
|
5
|
-
attr :numbers
|
6
|
-
attr :var
|
7
|
-
attr :var2
|
8
|
-
attr :var3
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@numbers = int_var_array(4, 0..9)
|
12
|
-
@var = int_var(-9..9)
|
13
|
-
@var2 = int_var(0..9)
|
14
|
-
@var3 = int_var(0..9)
|
15
|
-
branch_on @numbers
|
16
|
-
branch_on wrap_enum([@var, @var2, @var3])
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Construct a method placing expectations for an arithmetic constraint with the
|
21
|
-
# specified arity (number of variables before must) and the specified name in
|
22
|
-
# Gecode.
|
23
|
-
def arithmetic_expectation(gecode_name, arity)
|
24
|
-
lambda do |relation, rhs, strength, kind, reif_var, negated|
|
25
|
-
# Construct the arguments expected to be passed to the Gecode variant of
|
26
|
-
# the constraint.
|
27
|
-
rhs = an_instance_of(Gecode::Raw::IntVar) if rhs.respond_to? :bind
|
28
|
-
expected_gecode_arguments = [an_instance_of(Gecode::Raw::Space)]
|
29
|
-
arity.times do
|
30
|
-
expected_gecode_arguments << an_instance_of(Gecode::Raw::IntVar)
|
31
|
-
end
|
32
|
-
can_use_single_gecode_constraint = reif_var.nil? && !negated &&
|
33
|
-
relation == Gecode::Raw::IRT_EQ && !rhs.kind_of?(Fixnum)
|
34
|
-
if can_use_single_gecode_constraint
|
35
|
-
expected_gecode_arguments << rhs
|
36
|
-
else
|
37
|
-
expected_gecode_arguments << an_instance_of(Gecode::Raw::IntVar)
|
38
|
-
end
|
39
|
-
expected_gecode_arguments.concat([strength, kind])
|
40
|
-
|
41
|
-
# Create the actual method producing the expectation.
|
42
|
-
@model.allow_space_access do
|
43
|
-
if reif_var.nil?
|
44
|
-
if can_use_single_gecode_constraint
|
45
|
-
Gecode::Raw.should_receive(gecode_name).once.with(
|
46
|
-
*expected_gecode_arguments)
|
47
|
-
Gecode::Raw.should_receive(:rel).exactly(0).times
|
48
|
-
else
|
49
|
-
Gecode::Raw.should_receive(gecode_name).once.with(
|
50
|
-
*expected_gecode_arguments)
|
51
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
52
|
-
an_instance_of(Gecode::Raw::Space),
|
53
|
-
an_instance_of(Gecode::Raw::IntVar),
|
54
|
-
relation, rhs, strength, kind)
|
55
|
-
end
|
56
|
-
else
|
57
|
-
Gecode::Raw.should_receive(gecode_name).once.with(
|
58
|
-
*expected_gecode_arguments)
|
59
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
60
|
-
an_instance_of(Gecode::Raw::Space),
|
61
|
-
an_instance_of(Gecode::Raw::IntVar), relation, rhs,
|
62
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
63
|
-
strength, kind)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Requires @stub, @target, @model and @expect.
|
70
|
-
describe 'arithmetic constraint', :shared => true do
|
71
|
-
before do
|
72
|
-
# For constraint option spec.
|
73
|
-
@invoke_options = lambda do |hash|
|
74
|
-
@stub.must_be.greater_than(@target, hash)
|
75
|
-
@model.solve!
|
76
|
-
end
|
77
|
-
@expect_options = option_expectation do |strength, kind, reif_var|
|
78
|
-
@expect.call(Gecode::Raw::IRT_GR, @target, strength, kind, reif_var,
|
79
|
-
false)
|
80
|
-
end
|
81
|
-
|
82
|
-
# For composite spec.
|
83
|
-
@invoke_relation = lambda do |relation, target, negated|
|
84
|
-
if negated
|
85
|
-
@stub.must_not.send(relation, target)
|
86
|
-
else
|
87
|
-
@stub.must.send(relation, target)
|
88
|
-
end
|
89
|
-
@model.solve!
|
90
|
-
end
|
91
|
-
@expect_relation = lambda do |relation, target, negated|
|
92
|
-
@expect.call(relation, target, Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF,
|
93
|
-
nil, negated)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'should translate reification when using equality' do
|
98
|
-
bool_var = @model.bool_var
|
99
|
-
@expect.call(Gecode::Raw::IRT_EQ, @target, Gecode::Raw::ICL_DEF,
|
100
|
-
Gecode::Raw::PK_DEF, bool_var, false)
|
101
|
-
@stub.must_be.equal_to(@target, :reify => bool_var)
|
102
|
-
@model.solve!
|
103
|
-
end
|
104
|
-
|
105
|
-
it_should_behave_like 'composite constraint'
|
106
|
-
it_should_behave_like 'reifiable constraint'
|
107
|
-
end
|
108
|
-
|
109
|
-
describe Gecode::Constraints::IntEnum::Arithmetic, ' (max)' do
|
110
|
-
before do
|
111
|
-
@model = ArithmeticSampleProblem.new
|
112
|
-
@numbers = @model.numbers
|
113
|
-
@target = @var = @model.var
|
114
|
-
@stub = @numbers.max
|
115
|
-
|
116
|
-
# Creates an expectation corresponding to the specified input.
|
117
|
-
@expect = lambda do |relation, rhs, strength, kind, reif_var, negated|
|
118
|
-
@model.allow_space_access do
|
119
|
-
rhs = an_instance_of(Gecode::Raw::IntVar) if rhs.respond_to? :bind
|
120
|
-
if reif_var.nil?
|
121
|
-
if !negated and relation == Gecode::Raw::IRT_EQ and
|
122
|
-
!rhs.kind_of? Fixnum
|
123
|
-
Gecode::Raw.should_receive(:max).once.with(
|
124
|
-
an_instance_of(Gecode::Raw::Space),
|
125
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
126
|
-
rhs, strength, kind)
|
127
|
-
Gecode::Raw.should_receive(:rel).exactly(0).times
|
128
|
-
else
|
129
|
-
Gecode::Raw.should_receive(:max).once.with(
|
130
|
-
an_instance_of(Gecode::Raw::Space),
|
131
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
132
|
-
an_instance_of(Gecode::Raw::IntVar),
|
133
|
-
strength, kind)
|
134
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
135
|
-
an_instance_of(Gecode::Raw::Space),
|
136
|
-
an_instance_of(Gecode::Raw::IntVar),
|
137
|
-
relation, rhs, strength, kind)
|
138
|
-
end
|
139
|
-
else
|
140
|
-
Gecode::Raw.should_receive(:max).once.with(
|
141
|
-
an_instance_of(Gecode::Raw::Space),
|
142
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
143
|
-
an_instance_of(Gecode::Raw::IntVar),
|
144
|
-
strength, kind)
|
145
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
146
|
-
an_instance_of(Gecode::Raw::Space),
|
147
|
-
an_instance_of(Gecode::Raw::IntVar), relation, rhs,
|
148
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
149
|
-
strength, kind)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'should constrain the maximum value' do
|
156
|
-
@numbers.max.must > 5
|
157
|
-
@model.solve!.numbers.values.max.should > 5
|
158
|
-
end
|
159
|
-
|
160
|
-
it_should_behave_like 'arithmetic constraint'
|
161
|
-
end
|
162
|
-
|
163
|
-
describe Gecode::Constraints::IntEnum::Arithmetic, ' (min)' do
|
164
|
-
before do
|
165
|
-
@model = ArithmeticSampleProblem.new
|
166
|
-
@numbers = @model.numbers
|
167
|
-
@target = @var = @model.var
|
168
|
-
@stub = @numbers.min
|
169
|
-
|
170
|
-
# Creates an expectation corresponding to the specified input.
|
171
|
-
@expect = lambda do |relation, rhs, strength, kind, reif_var, negated|
|
172
|
-
@model.allow_space_access do
|
173
|
-
rhs = an_instance_of(Gecode::Raw::IntVar) if rhs.respond_to? :bind
|
174
|
-
if reif_var.nil?
|
175
|
-
if !negated and relation == Gecode::Raw::IRT_EQ and
|
176
|
-
!rhs.kind_of? Fixnum
|
177
|
-
Gecode::Raw.should_receive(:min).once.with(
|
178
|
-
an_instance_of(Gecode::Raw::Space),
|
179
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
180
|
-
rhs, strength, kind)
|
181
|
-
Gecode::Raw.should_receive(:rel).exactly(0).times
|
182
|
-
else
|
183
|
-
Gecode::Raw.should_receive(:min).once.with(
|
184
|
-
an_instance_of(Gecode::Raw::Space),
|
185
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
186
|
-
an_instance_of(Gecode::Raw::IntVar),
|
187
|
-
strength, kind)
|
188
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
189
|
-
an_instance_of(Gecode::Raw::Space),
|
190
|
-
an_instance_of(Gecode::Raw::IntVar),
|
191
|
-
relation, rhs, strength, kind)
|
192
|
-
end
|
193
|
-
else
|
194
|
-
Gecode::Raw.should_receive(:min).once.with(
|
195
|
-
an_instance_of(Gecode::Raw::Space),
|
196
|
-
an_instance_of(Gecode::Raw::IntVarArray),
|
197
|
-
an_instance_of(Gecode::Raw::IntVar),
|
198
|
-
strength, kind)
|
199
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
200
|
-
an_instance_of(Gecode::Raw::Space),
|
201
|
-
an_instance_of(Gecode::Raw::IntVar), relation, rhs,
|
202
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
203
|
-
strength, kind)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
it 'should constrain the minimum value' do
|
210
|
-
@numbers.min.must > 5
|
211
|
-
@model.solve!.numbers.values.min.should > 5
|
212
|
-
end
|
213
|
-
|
214
|
-
it_should_behave_like 'arithmetic constraint'
|
215
|
-
end
|
216
|
-
|
217
|
-
describe Gecode::Constraints::Int::Arithmetic, ' (abs)' do
|
218
|
-
before do
|
219
|
-
@model = ArithmeticSampleProblem.new
|
220
|
-
@var = @model.var
|
221
|
-
@target = @model.var2
|
222
|
-
@stub = @var.abs
|
223
|
-
|
224
|
-
# Creates an expectation corresponding to the specified input.
|
225
|
-
@expect = lambda do |relation, rhs, strength, kind, reif_var, negated|
|
226
|
-
@model.allow_space_access do
|
227
|
-
rhs = an_instance_of(Gecode::Raw::IntVar) if rhs.respond_to? :bind
|
228
|
-
if reif_var.nil?
|
229
|
-
if !negated and relation == Gecode::Raw::IRT_EQ and
|
230
|
-
!rhs.kind_of? Fixnum
|
231
|
-
Gecode::Raw.should_receive(:abs).once.with(
|
232
|
-
an_instance_of(Gecode::Raw::Space),
|
233
|
-
an_instance_of(Gecode::Raw::IntVar),
|
234
|
-
rhs, strength, kind)
|
235
|
-
Gecode::Raw.should_receive(:rel).exactly(0).times
|
236
|
-
else
|
237
|
-
Gecode::Raw.should_receive(:abs).once.with(
|
238
|
-
an_instance_of(Gecode::Raw::Space),
|
239
|
-
an_instance_of(Gecode::Raw::IntVar),
|
240
|
-
an_instance_of(Gecode::Raw::IntVar),
|
241
|
-
strength, kind)
|
242
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
243
|
-
an_instance_of(Gecode::Raw::Space),
|
244
|
-
an_instance_of(Gecode::Raw::IntVar),
|
245
|
-
relation, rhs, strength, kind)
|
246
|
-
end
|
247
|
-
else
|
248
|
-
Gecode::Raw.should_receive(:abs).once.with(
|
249
|
-
an_instance_of(Gecode::Raw::Space),
|
250
|
-
an_instance_of(Gecode::Raw::IntVar),
|
251
|
-
an_instance_of(Gecode::Raw::IntVar),
|
252
|
-
strength, kind)
|
253
|
-
Gecode::Raw.should_receive(:rel).once.with(
|
254
|
-
an_instance_of(Gecode::Raw::Space),
|
255
|
-
an_instance_of(Gecode::Raw::IntVar), relation, rhs,
|
256
|
-
an_instance_of(Gecode::Raw::BoolVar),
|
257
|
-
strength, kind)
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
it 'should constrain the absolute value' do
|
264
|
-
@var.must < 0
|
265
|
-
@var.abs.must == 5
|
266
|
-
@model.solve!.var.value.should == -5
|
267
|
-
end
|
268
|
-
|
269
|
-
it_should_behave_like 'arithmetic constraint'
|
270
|
-
end
|
271
|
-
|
272
|
-
describe Gecode::Constraints::Int::Arithmetic, ' (multiplication)' do
|
273
|
-
before do
|
274
|
-
@model = ArithmeticSampleProblem.new
|
275
|
-
@var = @model.var
|
276
|
-
@var2 = @model.var2
|
277
|
-
@stub = @var * @var2
|
278
|
-
@target = @model.var3
|
279
|
-
|
280
|
-
@expect = arithmetic_expectation(:mult, 2)
|
281
|
-
end
|
282
|
-
|
283
|
-
it 'should constrain the value of the multiplication' do
|
284
|
-
(@var * @var2).must == 56
|
285
|
-
sol = @model.solve!
|
286
|
-
[sol.var.value, sol.var2.value].sort.should == [7, 8]
|
287
|
-
end
|
288
|
-
|
289
|
-
it 'should not interfere with other defined multiplication methods' do
|
290
|
-
(@var * :foo).should be_nil
|
291
|
-
end
|
292
|
-
|
293
|
-
it_should_behave_like 'arithmetic constraint'
|
294
|
-
end
|
295
|
-
|
296
|
-
describe Gecode::Constraints::Int::Arithmetic, ' (squared)' do
|
297
|
-
before do
|
298
|
-
@model = ArithmeticSampleProblem.new
|
299
|
-
@var = @model.var
|
300
|
-
@stub = @var.squared
|
301
|
-
@target = @model.var2
|
302
|
-
|
303
|
-
@expect = arithmetic_expectation(:sqr, 1)
|
304
|
-
end
|
305
|
-
|
306
|
-
it 'should constrain the value of the variable squared' do
|
307
|
-
@var.squared.must == 9
|
308
|
-
sol = @model.solve!
|
309
|
-
sol.var.value.abs.should == 3
|
310
|
-
end
|
311
|
-
|
312
|
-
it_should_behave_like 'arithmetic constraint'
|
313
|
-
end
|
314
|
-
|
315
|
-
describe Gecode::Constraints::Int::Arithmetic, ' (square root)' do
|
316
|
-
before do
|
317
|
-
@model = ArithmeticSampleProblem.new
|
318
|
-
@var = @model.var
|
319
|
-
@stub = @var.square_root
|
320
|
-
@target = @model.var2
|
321
|
-
|
322
|
-
@expect = arithmetic_expectation(:sqrt, 1)
|
323
|
-
end
|
324
|
-
|
325
|
-
it 'should constrain the square root of the variable' do
|
326
|
-
@var.square_root.must == 3
|
327
|
-
sol = @model.solve!
|
328
|
-
Math.sqrt(sol.var.value).floor.should == 3
|
329
|
-
end
|
330
|
-
|
331
|
-
it 'should constrain the square root of the variable (2)' do
|
332
|
-
@var.square_root.must == 0
|
333
|
-
sol = @model.solve!
|
334
|
-
Math.sqrt(sol.var.value).floor.should == 0
|
335
|
-
end
|
336
|
-
|
337
|
-
it 'should constrain the square root of the variable (3)' do
|
338
|
-
@var.must < 0
|
339
|
-
@var.square_root.must == 0
|
340
|
-
@model.solve!.should be_nil
|
341
|
-
end
|
342
|
-
|
343
|
-
it 'should round down the square root' do
|
344
|
-
@var.must > 4
|
345
|
-
@var.square_root.must == 2
|
346
|
-
sol = @model.solve!
|
347
|
-
sol.var.value.should be_between(5,8)
|
348
|
-
end
|
349
|
-
|
350
|
-
it_should_behave_like 'arithmetic constraint'
|
351
|
-
end
|