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
data/specs/int_var.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/constraints/property_helper'
|
2
3
|
|
3
4
|
describe 'non-empty int variable', :shared => true do
|
4
5
|
it 'should have min equal to the lower domain bound' do
|
@@ -35,18 +36,22 @@ describe 'non-empty int variable', :shared => true do
|
|
35
36
|
it 'should have a zero degree' do
|
36
37
|
@var.degree.should be_zero
|
37
38
|
end
|
39
|
+
|
40
|
+
it 'should return the correct domain through #domain' do
|
41
|
+
@var.domain.to_a.should == @domain.to_a
|
42
|
+
end
|
43
|
+
|
44
|
+
it_should_behave_like 'int var operand'
|
38
45
|
end
|
39
46
|
|
40
|
-
describe Gecode::
|
47
|
+
describe Gecode::IntVar, ' (with range domain of size > 1)' do
|
41
48
|
before do
|
42
49
|
@range = -4..3
|
43
50
|
@domain = @range.to_a
|
44
|
-
model = Gecode::Model.new
|
45
|
-
@var = model.int_var(@range)
|
51
|
+
@model = Gecode::Model.new
|
52
|
+
@operand = @var = @model.int_var(@range)
|
46
53
|
end
|
47
54
|
|
48
|
-
it_should_behave_like 'non-empty int variable'
|
49
|
-
|
50
55
|
it 'should not be assigned' do
|
51
56
|
@var.should_not be_assigned
|
52
57
|
end
|
@@ -58,28 +63,28 @@ describe Gecode::FreeIntVar, ' (with range domain of size > 1)' do
|
|
58
63
|
it 'should raise error when trying to access assigned value' do
|
59
64
|
lambda{ @var.value }.should raise_error(RuntimeError)
|
60
65
|
end
|
66
|
+
|
67
|
+
it_should_behave_like 'non-empty int variable'
|
61
68
|
end
|
62
69
|
|
63
|
-
describe Gecode::
|
70
|
+
describe Gecode::IntVar, ' (defined with three-dot range)' do
|
64
71
|
before do
|
65
72
|
@range = -4...3
|
66
73
|
@domain = @range.to_a
|
67
|
-
model = Gecode::Model.new
|
68
|
-
@var = model.int_var(@range)
|
74
|
+
@model = Gecode::Model.new
|
75
|
+
@operand = @var = @model.int_var(@range)
|
69
76
|
end
|
70
77
|
|
71
78
|
it_should_behave_like 'non-empty int variable'
|
72
79
|
end
|
73
80
|
|
74
|
-
describe Gecode::
|
81
|
+
describe Gecode::IntVar, ' (with non-range domain of size > 1)' do
|
75
82
|
before do
|
76
83
|
@domain = [-3, -2, -1, 1]
|
77
|
-
model = Gecode::Model.new
|
78
|
-
@var = model.int_var(@domain)
|
84
|
+
@model = Gecode::Model.new
|
85
|
+
@operand = @var = @model.int_var(@domain)
|
79
86
|
end
|
80
87
|
|
81
|
-
it_should_behave_like 'non-empty int variable'
|
82
|
-
|
83
88
|
it 'should not be assigned' do
|
84
89
|
@var.should_not be_assigned
|
85
90
|
end
|
@@ -91,17 +96,17 @@ describe Gecode::FreeIntVar, ' (with non-range domain of size > 1)' do
|
|
91
96
|
it 'should not contain the domain\'s holes' do
|
92
97
|
@var.should_not include(0)
|
93
98
|
end
|
99
|
+
|
100
|
+
it_should_behave_like 'non-empty int variable'
|
94
101
|
end
|
95
102
|
|
96
|
-
describe Gecode::
|
103
|
+
describe Gecode::IntVar, ' (with a domain of size 1)' do
|
97
104
|
before do
|
98
105
|
@domain = [1]
|
99
|
-
model = Gecode::Model.new
|
100
|
-
@var = model.int_var(*@domain)
|
106
|
+
@model = Gecode::Model.new
|
107
|
+
@operand = @var = @model.int_var(*@domain)
|
101
108
|
end
|
102
109
|
|
103
|
-
it_should_behave_like 'non-empty int variable'
|
104
|
-
|
105
110
|
it 'should be assigned' do
|
106
111
|
@var.should be_assigned
|
107
112
|
end
|
@@ -109,13 +114,15 @@ describe Gecode::FreeIntVar, ' (with a domain of size 1)' do
|
|
109
114
|
it 'should be a range domain' do
|
110
115
|
@var.should be_range
|
111
116
|
end
|
117
|
+
|
118
|
+
it_should_behave_like 'non-empty int variable'
|
112
119
|
end
|
113
120
|
|
114
|
-
describe Gecode::
|
121
|
+
describe Gecode::IntVar, ' (assigned)' do
|
115
122
|
before do
|
116
123
|
@domain = 1
|
117
|
-
model = Gecode::Model.new
|
118
|
-
@var = model.int_var(*@domain)
|
124
|
+
@model = Gecode::Model.new
|
125
|
+
@operand = @var = @model.int_var(*@domain)
|
119
126
|
end
|
120
127
|
|
121
128
|
it 'should be assigned' do
|
@@ -125,13 +132,19 @@ describe Gecode::FreeIntVar, ' (assigned)' do
|
|
125
132
|
it 'should give the assigned number when inspecting' do
|
126
133
|
@var.inspect.should include(" #{@domain[0]}>")
|
127
134
|
end
|
135
|
+
|
136
|
+
it 'should return the correct domain through #domain' do
|
137
|
+
@var.domain.to_a.should == [@domain]
|
138
|
+
end
|
139
|
+
|
140
|
+
it_should_behave_like 'int var operand'
|
128
141
|
end
|
129
142
|
|
130
|
-
describe Gecode::
|
143
|
+
describe Gecode::IntVar, ' (not assigned)' do
|
131
144
|
before do
|
132
145
|
@domain = 1..2
|
133
|
-
model = Gecode::Model.new
|
134
|
-
@var = model.int_var(@domain)
|
146
|
+
@model = Gecode::Model.new
|
147
|
+
@operand = @var = @model.int_var(@domain)
|
135
148
|
end
|
136
149
|
|
137
150
|
it 'should not be assigned' do
|
@@ -141,4 +154,10 @@ describe Gecode::FreeIntVar, ' (not assigned)' do
|
|
141
154
|
it 'should give the domain range when inspecting' do
|
142
155
|
@var.inspect.should include(" #{@domain.first}..#{@domain.last}>")
|
143
156
|
end
|
144
|
-
|
157
|
+
|
158
|
+
it 'should return the correct domain through #domain' do
|
159
|
+
@var.domain.to_a.should == @domain.to_a
|
160
|
+
end
|
161
|
+
|
162
|
+
it_should_behave_like 'int var operand'
|
163
|
+
end
|
data/specs/model.rb
CHANGED
@@ -265,4 +265,61 @@ describe Gecode::Model, ' (space access restriction)' do
|
|
265
265
|
end
|
266
266
|
end.should_not raise_error(RuntimeError)
|
267
267
|
end
|
268
|
-
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe Gecode::Model, ' (accessible variable creation)' do
|
271
|
+
before do
|
272
|
+
@model = Class.new(Gecode::Model).new
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'should allow creation of named variable using #foo_is_a' do
|
276
|
+
var = @model.int_var(17)
|
277
|
+
lambda{ @model.foo }.should raise_error(NoMethodError)
|
278
|
+
@model.instance_eval{ foo_is_a var }
|
279
|
+
lambda{ @model.foo }.should_not raise_error
|
280
|
+
@model.foo.should == var
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'should allow creation of named variable using #foo_is_an' do
|
284
|
+
var = @model.int_var(17)
|
285
|
+
lambda{ @model.foo }.should raise_error(NoMethodError)
|
286
|
+
@model.instance_eval{ foo_is_an var }
|
287
|
+
lambda{ @model.foo }.should_not raise_error
|
288
|
+
@model.foo.should == var
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'should only allow one argument to be given to #foo_is_a' do
|
292
|
+
lambda do
|
293
|
+
@model.instance_eval{ foo_is_a }
|
294
|
+
end.should raise_error(ArgumentError)
|
295
|
+
lambda do
|
296
|
+
@model.instance_eval{ foo_is_a bool_var, bool_var }
|
297
|
+
end.should raise_error(ArgumentError)
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'should only define the variable in the current instance' do
|
301
|
+
klass = Class.new Gecode::Model
|
302
|
+
model_a = klass.new
|
303
|
+
model_b = klass.new
|
304
|
+
|
305
|
+
model_a.instance_eval{ bar_is_a bool_var }
|
306
|
+
lambda{ model_a.bar }.should_not raise_error
|
307
|
+
lambda{ model_b.bar }.should raise_error(NoMethodError)
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'should raise error if a method would be overwritten' do
|
311
|
+
var = @model.int_var(17)
|
312
|
+
lambda{ @model.class }.should_not raise_error
|
313
|
+
lambda do
|
314
|
+
@model.instance_eval{ class_is_an var }
|
315
|
+
end.should raise_error(ArgumentError)
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'should raise error if an instance variable would be overwritten' do
|
319
|
+
@model.instance_eval{ @foo = 17 }
|
320
|
+
var = @model.int_var(17)
|
321
|
+
lambda do
|
322
|
+
@model.instance_eval{ foo_is_a var }
|
323
|
+
end.should raise_error(ArgumentError)
|
324
|
+
end
|
325
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Gecode, ' (Model sugar)' do
|
4
|
+
it 'should provide #solve as sugar for constructing a model and running solve!' do
|
5
|
+
Gecode.solve do
|
6
|
+
numbers_is_an int_var_array(2, 0..5)
|
7
|
+
x, y = numbers
|
8
|
+
(x * y).must == 25
|
9
|
+
branch_on numbers
|
10
|
+
end.numbers.values.should == [5,5]
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should provide #maximize as sugar for constructing a model and running maximize!' do
|
14
|
+
Gecode.maximize :z do
|
15
|
+
z_is_an int_var
|
16
|
+
x, y = vars = int_var_array(2, 0..5)
|
17
|
+
(x*2 - y).must == z
|
18
|
+
branch_on vars
|
19
|
+
end.z.value.should equal(10)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should provide #minimize as sugar for constructing a model and running minimize!' do
|
23
|
+
Gecode.minimize :z do
|
24
|
+
z_is_an int_var
|
25
|
+
x, y = vars = int_var_array(2, 0..5)
|
26
|
+
(x*2 - y).must == z
|
27
|
+
branch_on vars
|
28
|
+
end.z.value.should equal(-5)
|
29
|
+
end
|
30
|
+
end
|
data/specs/search.rb
CHANGED
@@ -201,16 +201,35 @@ describe Gecode::Model, ' (without solution)' do
|
|
201
201
|
end
|
202
202
|
|
203
203
|
it 'should return nil when calling #solution' do
|
204
|
-
@model.var.must < 0
|
205
204
|
@model.solution{ |s| 'test' }.should be_nil
|
206
205
|
end
|
206
|
+
|
207
|
+
it 'should not yield anything to #each_solution' do
|
208
|
+
@model.each_solution{ |s| violated }
|
209
|
+
end
|
207
210
|
|
208
|
-
it 'should
|
209
|
-
|
211
|
+
it 'should raise NoSolutionError when calling #solve!' do
|
212
|
+
lambda do
|
213
|
+
@model.solve!
|
214
|
+
end.should raise_error(Gecode::NoSolutionError)
|
210
215
|
end
|
211
216
|
|
212
|
-
it 'should
|
213
|
-
|
217
|
+
it 'should raise NoSolutionError when calling #optimize!' do
|
218
|
+
lambda do
|
219
|
+
@model.optimize!{}
|
220
|
+
end.should raise_error(Gecode::NoSolutionError)
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'should raise NoSolutionError when calling #minimize!' do
|
224
|
+
lambda do
|
225
|
+
@model.optimize!{}
|
226
|
+
end.should raise_error(Gecode::NoSolutionError)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should raise NoSolutionError when calling #maximize!' do
|
230
|
+
lambda do
|
231
|
+
@model.maximize!(:var)
|
232
|
+
end.should raise_error(Gecode::NoSolutionError)
|
214
233
|
end
|
215
234
|
end
|
216
235
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Gecode::SelectedSet::SelectedSetOperand do
|
4
|
+
before do
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
set_enum = @model.set_var_array(5, [], 0..9)
|
7
|
+
set = @model.set_var([], 0..4)
|
8
|
+
@operand = Gecode::SelectedSet::SelectedSetOperand.new(
|
9
|
+
set_enum, set)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should implement #model' do
|
13
|
+
@operand.model.should be_kind_of(Gecode::Model)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should implement #to_selected_set' do
|
17
|
+
enum, set = @operand.to_selected_set
|
18
|
+
enum.should be_respond_to(:to_set_enum)
|
19
|
+
set.should be_respond_to(:to_set_var)
|
20
|
+
@model.solve!
|
21
|
+
set_var = set.to_set_var
|
22
|
+
((set_var.lower_bound == []) &&
|
23
|
+
(set_var.upper_bound == Gecode::Model::LARGEST_SET_BOUND)).should_not(
|
24
|
+
be_true)
|
25
|
+
enum.each do |element|
|
26
|
+
set_var = element.to_set_var
|
27
|
+
((set_var.lower_bound == []) &&
|
28
|
+
(set_var.upper_bound == Gecode::Model::LARGEST_SET_BOUND)).should_not(
|
29
|
+
be_true)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should implement #must' do
|
34
|
+
receiver = @operand.must
|
35
|
+
receiver.should be_kind_of(
|
36
|
+
Gecode::SelectedSet::SelectedSetConstraintReceiver)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Gecode::SelectedSet::SelectedSetOperand do
|
4
|
+
before do
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
@set = @model.set_var([], 0..4)
|
7
|
+
@operand = Gecode::SetElements::SetElementsOperand.new(@set)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should implement #model' do
|
11
|
+
@operand.model.should be_kind_of(Gecode::Model)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should implement #to_set_elements' do
|
15
|
+
set = @operand.to_set_elements
|
16
|
+
set.should be_respond_to(:to_set_var)
|
17
|
+
@model.solve!
|
18
|
+
set_var = set.to_set_var
|
19
|
+
((set_var.lower_bound == []) &&
|
20
|
+
(set_var.upper_bound == Gecode::Model::LARGEST_SET_BOUND)).should_not(
|
21
|
+
be_true)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should implement #must' do
|
25
|
+
receiver = @operand.must
|
26
|
+
receiver.should be_kind_of(
|
27
|
+
Gecode::SetElements::SetElementsConstraintReceiver)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should be produces by SetOperand#elements' do
|
31
|
+
@set.elements.should be_respond_to(:to_set_elements)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
data/specs/set_var.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/
|
1
|
+
require File.dirname(__FILE__) + '/constraints/property_helper'
|
2
2
|
|
3
|
-
describe Gecode::
|
3
|
+
describe Gecode::SetVar, '(not assigned)' do
|
4
4
|
before do
|
5
|
-
model = Gecode::Model.new
|
6
|
-
@var = model.set_var(1..3, 0..4)
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
@operand = @var = @model.set_var(1..3, 0..4)
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'should not be assigned' do
|
@@ -14,6 +14,11 @@ describe Gecode::FreeSetVar, '(not assigned)' do
|
|
14
14
|
@var.inspect.should include('lub-range')
|
15
15
|
@var.inspect.should include('glb-range')
|
16
16
|
end
|
17
|
+
|
18
|
+
it 'should allow inspection even when the bounds are too large to display' do
|
19
|
+
var = @model.set_var
|
20
|
+
var.inspect.should include('too large')
|
21
|
+
end
|
17
22
|
|
18
23
|
it 'should report the correct bounds' do
|
19
24
|
@var.lower_bound.sort.to_a.should == (1..3).to_a
|
@@ -42,13 +47,15 @@ describe Gecode::FreeSetVar, '(not assigned)' do
|
|
42
47
|
lower_bound.each{}
|
43
48
|
end.should_not raise_error
|
44
49
|
end
|
50
|
+
|
51
|
+
it_should_behave_like 'set var operand'
|
45
52
|
end
|
46
53
|
|
47
|
-
describe Gecode::
|
54
|
+
describe Gecode::SetVar, '(assigned)' do
|
48
55
|
before do
|
49
|
-
model = Gecode::Model.new
|
50
|
-
@var = model.set_var(1, 1)
|
51
|
-
model.solve!
|
56
|
+
@model = Gecode::Model.new
|
57
|
+
@operand = @var = @model.set_var(1, 1)
|
58
|
+
@model.solve!
|
52
59
|
end
|
53
60
|
|
54
61
|
it 'should be assigned' do
|
@@ -65,4 +72,11 @@ describe Gecode::FreeSetVar, '(assigned)' do
|
|
65
72
|
@var.lower_bound.to_a.should == [1]
|
66
73
|
@var.value.to_a.should == [1]
|
67
74
|
end
|
75
|
+
|
76
|
+
it 'should allow inspection even when the bounds are too large to display' do
|
77
|
+
var = @model.set_var(0..10**4, 0..10**4)
|
78
|
+
var.inspect.should include('too large')
|
79
|
+
end
|
80
|
+
|
81
|
+
it_should_behave_like 'set var operand'
|
68
82
|
end
|
data/specs/spec_helper.rb
CHANGED
@@ -5,16 +5,25 @@ require File.dirname(__FILE__) + '/../lib/gecoder'
|
|
5
5
|
module CustomVarMatchers
|
6
6
|
class HaveDomain
|
7
7
|
def initialize(expected)
|
8
|
-
@expected = expected
|
8
|
+
@expected = expected
|
9
9
|
end
|
10
10
|
|
11
11
|
def matches?(target)
|
12
12
|
@target = target
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
if @expected.kind_of? Range
|
14
|
+
last = @expected.end
|
15
|
+
last -= 1 if @expected.exclude_end?
|
16
|
+
return @target.range? && @expected.begin == @target.min &&
|
17
|
+
last == @target.max
|
18
|
+
else
|
19
|
+
@expected = @expected.to_a
|
20
|
+
return false unless @target.size == @expected.size
|
21
|
+
@expected.each do |element|
|
22
|
+
return false unless @target.include? element
|
23
|
+
end
|
24
|
+
return true
|
16
25
|
end
|
17
|
-
return
|
26
|
+
return false
|
18
27
|
end
|
19
28
|
|
20
29
|
def failure_message
|
@@ -39,7 +48,9 @@ module CustomVarMatchers
|
|
39
48
|
|
40
49
|
def matches?(target)
|
41
50
|
@target = target
|
42
|
-
return @target.lower_bound.
|
51
|
+
return @target.lower_bound.size == @expected_glb.size &&
|
52
|
+
@target.upper_bound.size == @expected_lub.size &&
|
53
|
+
@target.lower_bound.to_a == @expected_glb &&
|
43
54
|
@target.upper_bound.to_a == @expected_lub
|
44
55
|
end
|
45
56
|
|
@@ -63,3 +74,192 @@ end
|
|
63
74
|
Spec::Runner.configure do |config|
|
64
75
|
config.include(CustomVarMatchers)
|
65
76
|
end
|
77
|
+
|
78
|
+
|
79
|
+
# Help methods for the GecodeR specs.
|
80
|
+
module GecodeR::Specs
|
81
|
+
module SetHelper
|
82
|
+
module_function
|
83
|
+
|
84
|
+
# Returns the arguments that should be used in a partial mock to expect the
|
85
|
+
# specified constant set (possibly an array of arguments).
|
86
|
+
def expect_constant_set(constant_set)
|
87
|
+
if constant_set.kind_of? Range
|
88
|
+
return constant_set.first, constant_set.last
|
89
|
+
elsif constant_set.kind_of? Fixnum
|
90
|
+
constant_set
|
91
|
+
else
|
92
|
+
an_instance_of(Gecode::Raw::IntSet)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
module GeneralHelper
|
98
|
+
module_function
|
99
|
+
|
100
|
+
# Produces a base operand that can be used to mock specific types of
|
101
|
+
# operands.
|
102
|
+
def general_operand_base(model)
|
103
|
+
mock_op_class = Class.new
|
104
|
+
mock_op_class.class_eval do
|
105
|
+
attr :model
|
106
|
+
|
107
|
+
def bind
|
108
|
+
raise 'Bind should not be called directly for an operand.'
|
109
|
+
end
|
110
|
+
alias_method :bind_array, :bind
|
111
|
+
end
|
112
|
+
op = mock_op_class.new
|
113
|
+
op.instance_eval do
|
114
|
+
@model = model
|
115
|
+
end
|
116
|
+
return op
|
117
|
+
end
|
118
|
+
|
119
|
+
# Produces a general int operand. The method returns two objects:
|
120
|
+
# the operand itself and the variable it returns when #to_int_var
|
121
|
+
# is called.
|
122
|
+
def general_int_operand(model)
|
123
|
+
op = general_operand_base(model)
|
124
|
+
|
125
|
+
int_var = model.int_var
|
126
|
+
class <<op
|
127
|
+
include Gecode::Int::IntOperand
|
128
|
+
attr :model
|
129
|
+
end
|
130
|
+
op.stub!(:to_int_var).and_return int_var
|
131
|
+
|
132
|
+
return op, int_var
|
133
|
+
end
|
134
|
+
|
135
|
+
# Produces a general bool operand. The method returns two objects:
|
136
|
+
# the operand itself and the variable it returns when #to_bool_var
|
137
|
+
# is called.
|
138
|
+
def general_bool_operand(model)
|
139
|
+
op = general_operand_base(model)
|
140
|
+
|
141
|
+
bool_var = model.bool_var
|
142
|
+
class <<op
|
143
|
+
include Gecode::Bool::BoolOperand
|
144
|
+
attr :model
|
145
|
+
end
|
146
|
+
op.stub!(:to_bool_var).and_return bool_var
|
147
|
+
|
148
|
+
return op, bool_var
|
149
|
+
end
|
150
|
+
|
151
|
+
# Produces a general set operand. The method returns two objects:
|
152
|
+
# the operand itself and the variable it returns when #to_set_var
|
153
|
+
# is called.
|
154
|
+
def general_set_operand(model)
|
155
|
+
op = general_operand_base(model)
|
156
|
+
|
157
|
+
set_var = model.set_var
|
158
|
+
class <<op
|
159
|
+
include Gecode::Set::SetOperand
|
160
|
+
attr :model
|
161
|
+
end
|
162
|
+
op.stub!(:to_set_var).and_return set_var
|
163
|
+
|
164
|
+
return op, set_var
|
165
|
+
end
|
166
|
+
|
167
|
+
# Produces a general int enum operand. The method returns two objects:
|
168
|
+
# the operand itself and the variable it returns when #to_int_enum
|
169
|
+
# is called.
|
170
|
+
def general_int_enum_operand(model)
|
171
|
+
op = general_operand_base(model)
|
172
|
+
|
173
|
+
int_enum = model.int_var_array(5)
|
174
|
+
class <<op
|
175
|
+
include Gecode::IntEnum::IntEnumOperand
|
176
|
+
attr :model
|
177
|
+
end
|
178
|
+
op.stub!(:to_int_enum).and_return int_enum
|
179
|
+
|
180
|
+
return op, int_enum
|
181
|
+
end
|
182
|
+
|
183
|
+
# Produces a general bool enum operand. The method returns two objects:
|
184
|
+
# the operand itself and the variable it returns when #to_bool_enum
|
185
|
+
# is called.
|
186
|
+
def general_bool_enum_operand(model)
|
187
|
+
op = general_operand_base(model)
|
188
|
+
|
189
|
+
bool_enum = model.bool_var_array(5)
|
190
|
+
class <<op
|
191
|
+
include Gecode::BoolEnum::BoolEnumOperand
|
192
|
+
attr :model
|
193
|
+
end
|
194
|
+
op.stub!(:to_bool_enum).and_return bool_enum
|
195
|
+
|
196
|
+
return op, bool_enum
|
197
|
+
end
|
198
|
+
|
199
|
+
# Produces a general set enum operand. The method returns two objects:
|
200
|
+
# the operand itself and the variable it returns when #to_set_enum
|
201
|
+
# is called.
|
202
|
+
def general_set_enum_operand(model)
|
203
|
+
op = general_operand_base(model)
|
204
|
+
|
205
|
+
set_enum = model.set_var_array(5)
|
206
|
+
class <<op
|
207
|
+
include Gecode::SetEnum::SetEnumOperand
|
208
|
+
attr :model
|
209
|
+
end
|
210
|
+
op.stub!(:to_set_enum).and_return set_enum
|
211
|
+
|
212
|
+
return op, set_enum
|
213
|
+
end
|
214
|
+
|
215
|
+
# Produces a general selected set operand. The method returns two objects:
|
216
|
+
# the operand itself and the array of variables corresponding to the
|
217
|
+
# operands it returns when # #to_selected_set is called.
|
218
|
+
def general_selected_set_operand(model)
|
219
|
+
set_enum, set_enum_var = general_set_enum_operand(model)
|
220
|
+
set, set_var = general_set_operand(model)
|
221
|
+
op = Gecode::SelectedSet::SelectedSetOperand.new(
|
222
|
+
set_enum, set)
|
223
|
+
return op, [set_enum_var, set_var]
|
224
|
+
end
|
225
|
+
|
226
|
+
# Produces a general set elements operand. The method returns two
|
227
|
+
# objects: the operand itself and the set var corresponding to the
|
228
|
+
# operands it returns when # #to_selected_set is called.
|
229
|
+
def general_set_elements_operand(model)
|
230
|
+
set, set_var = general_set_operand(model)
|
231
|
+
op = Gecode::SetElements::SetElementsOperand.new(set)
|
232
|
+
return op, set_var
|
233
|
+
end
|
234
|
+
|
235
|
+
# Produces a general fixnum enum operand. The method returns two objects:
|
236
|
+
# the operand itself and the variable it returns when #to_fixnum_enum
|
237
|
+
# is called.
|
238
|
+
def general_fixnum_enum_operand(model)
|
239
|
+
op = general_operand_base(model)
|
240
|
+
|
241
|
+
fixnum_enum = model.wrap_enum([1, -4, 9, 4, 0])
|
242
|
+
class <<op
|
243
|
+
include Gecode::FixnumEnum::FixnumEnumOperand
|
244
|
+
attr :model
|
245
|
+
end
|
246
|
+
op.stub!(:to_fixnum_enum).and_return fixnum_enum
|
247
|
+
|
248
|
+
return op, fixnum_enum
|
249
|
+
end
|
250
|
+
|
251
|
+
# Produces an array of general operands of the specified types.
|
252
|
+
# Returns an array of operands and an array of their variables.
|
253
|
+
def produce_general_arguments(property_types)
|
254
|
+
operands = []
|
255
|
+
variables = []
|
256
|
+
property_types.each do |type|
|
257
|
+
op, var = eval "general_#{type}_operand(@model)"
|
258
|
+
operands << op
|
259
|
+
variables << var
|
260
|
+
end
|
261
|
+
return operands, variables
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
include GecodeR::Specs::GeneralHelper
|