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.
Files changed (142) hide show
  1. data/CHANGES +15 -0
  2. data/README +6 -2
  3. data/example/equation_system.rb +15 -0
  4. data/example/magic_sequence.rb +7 -7
  5. data/example/money.rb +36 -0
  6. data/example/queens.rb +7 -8
  7. data/example/send_most_money.rb +1 -1
  8. data/example/square_tiling.rb +2 -2
  9. data/example/sudoku-set.rb +11 -12
  10. data/example/sudoku.rb +40 -45
  11. data/ext/extconf.rb +0 -0
  12. data/lib/gecoder/bindings.rb +42 -0
  13. data/lib/gecoder/bindings/bindings.rb +16 -0
  14. data/lib/gecoder/interface.rb +2 -1
  15. data/lib/gecoder/interface/branch.rb +16 -9
  16. data/lib/gecoder/interface/constraints.rb +410 -451
  17. data/lib/gecoder/interface/constraints/bool/boolean.rb +205 -213
  18. data/lib/gecoder/interface/constraints/bool/channel.rb +4 -5
  19. data/lib/gecoder/interface/constraints/bool/linear.rb +192 -21
  20. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +43 -39
  21. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +43 -49
  22. data/lib/gecoder/interface/constraints/bool_enum/relation.rb +38 -71
  23. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +73 -22
  24. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +140 -61
  25. data/lib/gecoder/interface/constraints/extensional_regexp.rb +4 -4
  26. data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
  27. data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
  28. data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
  29. data/lib/gecoder/interface/constraints/int/arithmetic.rb +131 -130
  30. data/lib/gecoder/interface/constraints/int/channel.rb +21 -31
  31. data/lib/gecoder/interface/constraints/int/domain.rb +45 -42
  32. data/lib/gecoder/interface/constraints/int/linear.rb +85 -239
  33. data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
  34. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +55 -64
  35. data/lib/gecoder/interface/constraints/int_enum/channel.rb +35 -37
  36. data/lib/gecoder/interface/constraints/int_enum/count.rb +53 -78
  37. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +36 -46
  38. data/lib/gecoder/interface/constraints/int_enum/element.rb +39 -57
  39. data/lib/gecoder/interface/constraints/int_enum/equality.rb +15 -19
  40. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +65 -72
  41. data/lib/gecoder/interface/constraints/int_enum/sort.rb +42 -45
  42. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +79 -22
  43. data/lib/gecoder/interface/constraints/int_var_constraints.rb +215 -44
  44. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +14 -14
  45. data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
  46. data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
  47. data/lib/gecoder/interface/constraints/set/cardinality.rb +43 -53
  48. data/lib/gecoder/interface/constraints/set/channel.rb +26 -29
  49. data/lib/gecoder/interface/constraints/set/connection.rb +89 -152
  50. data/lib/gecoder/interface/constraints/set/domain.rb +112 -65
  51. data/lib/gecoder/interface/constraints/set/include.rb +36 -0
  52. data/lib/gecoder/interface/constraints/set/operation.rb +96 -110
  53. data/lib/gecoder/interface/constraints/set/relation.rb +114 -137
  54. data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
  55. data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
  56. data/lib/gecoder/interface/constraints/set_enum/channel.rb +23 -27
  57. data/lib/gecoder/interface/constraints/set_enum/distinct.rb +18 -19
  58. data/lib/gecoder/interface/constraints/set_enum/operation.rb +62 -53
  59. data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
  60. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +73 -23
  61. data/lib/gecoder/interface/constraints/set_var_constraints.rb +222 -57
  62. data/lib/gecoder/interface/enum_matrix.rb +4 -4
  63. data/lib/gecoder/interface/enum_wrapper.rb +71 -22
  64. data/lib/gecoder/interface/model.rb +167 -12
  65. data/lib/gecoder/interface/model_sugar.rb +84 -0
  66. data/lib/gecoder/interface/search.rb +30 -18
  67. data/lib/gecoder/interface/variables.rb +103 -33
  68. data/lib/gecoder/version.rb +2 -2
  69. data/specs/bool_var.rb +19 -12
  70. data/specs/constraints/{boolean.rb → bool/boolean.rb} +103 -28
  71. data/specs/constraints/bool/boolean_properties.rb +51 -0
  72. data/specs/constraints/bool/linear.rb +213 -0
  73. data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
  74. data/specs/constraints/bool_enum/channel.rb +102 -0
  75. data/specs/constraints/{extensional.rb → bool_enum/extensional.rb} +32 -101
  76. data/specs/constraints/constraint_helper.rb +149 -179
  77. data/specs/constraints/constraint_receivers.rb +103 -0
  78. data/specs/constraints/constraints.rb +6 -63
  79. data/specs/constraints/fixnum_enum/element.rb +58 -0
  80. data/specs/constraints/fixnum_enum/operation.rb +67 -0
  81. data/specs/constraints/int/arithmetic.rb +149 -0
  82. data/specs/constraints/int/channel.rb +101 -0
  83. data/specs/constraints/int/domain.rb +106 -0
  84. data/specs/constraints/int/linear.rb +183 -0
  85. data/specs/constraints/int/linear_properties.rb +97 -0
  86. data/specs/constraints/int/relation.rb +84 -0
  87. data/specs/constraints/int_enum/arithmetic.rb +72 -0
  88. data/specs/constraints/int_enum/channel.rb +57 -0
  89. data/specs/constraints/int_enum/count.rb +72 -0
  90. data/specs/constraints/int_enum/distinct.rb +80 -0
  91. data/specs/constraints/int_enum/element.rb +61 -0
  92. data/specs/constraints/int_enum/equality.rb +29 -0
  93. data/specs/constraints/int_enum/extensional.rb +224 -0
  94. data/specs/constraints/int_enum/sort.rb +167 -0
  95. data/specs/constraints/operands.rb +264 -0
  96. data/specs/constraints/property_helper.rb +443 -0
  97. data/specs/constraints/reification_sugar.rb +4 -5
  98. data/specs/constraints/selected_set/select.rb +56 -0
  99. data/specs/constraints/selected_set/select_properties.rb +157 -0
  100. data/specs/constraints/set/cardinality.rb +58 -0
  101. data/specs/constraints/set/cardinality_properties.rb +46 -0
  102. data/specs/constraints/set/channel.rb +77 -0
  103. data/specs/constraints/set/connection.rb +176 -0
  104. data/specs/constraints/set/domain.rb +197 -0
  105. data/specs/constraints/set/include.rb +36 -0
  106. data/specs/constraints/set/operation.rb +132 -0
  107. data/specs/constraints/set/relation.rb +117 -0
  108. data/specs/constraints/set_elements/relation.rb +84 -0
  109. data/specs/constraints/set_enum/channel.rb +80 -0
  110. data/specs/constraints/set_enum/distinct.rb +59 -0
  111. data/specs/constraints/set_enum/operation.rb +111 -0
  112. data/specs/constraints/set_enum/select.rb +73 -0
  113. data/specs/enum_wrapper.rb +53 -3
  114. data/specs/int_var.rb +44 -25
  115. data/specs/model.rb +58 -1
  116. data/specs/model_sugar.rb +30 -0
  117. data/specs/search.rb +24 -5
  118. data/specs/selected_set.rb +39 -0
  119. data/specs/set_elements.rb +34 -0
  120. data/specs/set_var.rb +22 -8
  121. data/specs/spec_helper.rb +206 -6
  122. data/tasks/distribution.rake +22 -7
  123. data/tasks/svn.rake +3 -1
  124. metadata +218 -134
  125. data/lib/gecoder/interface/constraints/set_enum/selection.rb +0 -217
  126. data/specs/constraints/arithmetic.rb +0 -351
  127. data/specs/constraints/bool_enum_relation.rb +0 -160
  128. data/specs/constraints/cardinality.rb +0 -157
  129. data/specs/constraints/channel.rb +0 -454
  130. data/specs/constraints/connection.rb +0 -369
  131. data/specs/constraints/count.rb +0 -146
  132. data/specs/constraints/distinct.rb +0 -164
  133. data/specs/constraints/element.rb +0 -108
  134. data/specs/constraints/equality.rb +0 -31
  135. data/specs/constraints/int_domain.rb +0 -70
  136. data/specs/constraints/int_relation.rb +0 -82
  137. data/specs/constraints/linear.rb +0 -340
  138. data/specs/constraints/selection.rb +0 -292
  139. data/specs/constraints/set_domain.rb +0 -185
  140. data/specs/constraints/set_operation.rb +0 -285
  141. data/specs/constraints/set_relation.rb +0 -197
  142. 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