gecoder 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/CHANGES +17 -2
  2. data/README +7 -1
  3. data/Rakefile +4 -0
  4. data/lib/gecoder/interface/constraints/bool/boolean.rb +1 -4
  5. data/lib/gecoder/interface/constraints/int/arithmetic.rb +77 -0
  6. data/lib/gecoder/interface/constraints/int/domain.rb +50 -0
  7. data/lib/gecoder/interface/constraints/int/linear.rb +12 -44
  8. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +72 -0
  9. data/lib/gecoder/interface/constraints/int_enum/channel.rb +32 -0
  10. data/lib/gecoder/interface/constraints/int_enum/count.rb +90 -0
  11. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +3 -8
  12. data/lib/gecoder/interface/constraints/int_enum/element.rb +75 -0
  13. data/lib/gecoder/interface/constraints/int_enum/equality.rb +31 -0
  14. data/lib/gecoder/interface/constraints/int_enum/sort.rb +104 -0
  15. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +6 -0
  16. data/lib/gecoder/interface/constraints/int_var_constraints.rb +2 -0
  17. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +21 -0
  18. data/lib/gecoder/interface/constraints.rb +57 -6
  19. data/lib/gecoder/interface/enum_matrix.rb +64 -0
  20. data/lib/gecoder/interface/enum_wrapper.rb +33 -5
  21. data/lib/gecoder/interface/model.rb +36 -6
  22. data/lib/gecoder/interface.rb +1 -0
  23. data/lib/gecoder/version.rb +4 -0
  24. data/lib/gecoder.rb +1 -0
  25. data/specs/binding_changes.rb +72 -0
  26. data/specs/bool_var.rb +20 -0
  27. data/specs/branch.rb +104 -0
  28. data/specs/constraints/arithmetic.rb +227 -0
  29. data/specs/constraints/boolean.rb +132 -0
  30. data/specs/constraints/channel.rb +55 -0
  31. data/specs/constraints/constraint_helper.rb +48 -0
  32. data/specs/constraints/constraints.rb +28 -0
  33. data/specs/constraints/count.rb +99 -0
  34. data/specs/constraints/distinct.rb +99 -0
  35. data/specs/constraints/domain.rb +56 -0
  36. data/specs/constraints/element.rb +128 -0
  37. data/specs/constraints/equality.rb +30 -0
  38. data/specs/constraints/linear.rb +166 -0
  39. data/specs/constraints/reification_sugar.rb +92 -0
  40. data/specs/constraints/relation.rb +72 -0
  41. data/specs/constraints/sort.rb +173 -0
  42. data/specs/enum_matrix.rb +43 -0
  43. data/specs/enum_wrapper.rb +100 -0
  44. data/specs/int_var.rb +108 -0
  45. data/specs/model.rb +84 -0
  46. data/specs/search.rb +157 -0
  47. data/specs/spec_helper.rb +63 -0
  48. data/specs/tmp +135 -0
  49. data/tasks/all_tasks.rb +1 -0
  50. data/tasks/distribution.rake +64 -0
  51. data/tasks/rcov.rake +17 -0
  52. data/tasks/specs.rake +16 -0
  53. data/tasks/svn.rake +11 -0
  54. data/tasks/website.rake +58 -0
  55. data/vendor/rust/include/rust_conversions.hh +1 -2
  56. metadata +53 -2
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/constraint_helper'
3
+
4
+ describe Gecode::Constraints::Int::Domain do
5
+ before do
6
+ @model = Gecode::Model.new
7
+ @domain = 0..3
8
+ @x = @model.int_var(@domain)
9
+ @range_domain = 1..2
10
+ @three_dot_range_domain = 1...2
11
+ @non_range_domain = [1, 3]
12
+
13
+ @invoke_options = lambda do |hash|
14
+ @x.must_be.in(@non_range_domain, hash)
15
+ @model.solve!
16
+ end
17
+ @expect_options = lambda do |strength, reif_var|
18
+ if reif_var.nil?
19
+ Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
20
+ @x.bind, an_instance_of(Gecode::Raw::IntSet), strength)
21
+ else
22
+ Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
23
+ @x.bind, an_instance_of(Gecode::Raw::IntSet),
24
+ an_instance_of(Gecode::Raw::BoolVar), strength)
25
+ end
26
+ end
27
+ end
28
+
29
+ it 'should translate domain constraints with range domains' do
30
+ Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
31
+ @x.bind, @range_domain.first, @range_domain.last, Gecode::Raw::ICL_DEF)
32
+ @x.must_be.in @range_domain
33
+ @model.solve!
34
+ end
35
+
36
+ it 'should translate domain constraints with three dot range domains' do
37
+ Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
38
+ @x.bind, @three_dot_range_domain.first, @three_dot_range_domain.last,
39
+ Gecode::Raw::ICL_DEF)
40
+ @x.must_be.in @three_dot_range_domain
41
+ @model.solve!
42
+ end
43
+
44
+ it 'should translate domain constraints with non-range domains' do
45
+ @expect_options.call(Gecode::Raw::ICL_DEF, nil)
46
+ @invoke_options.call({})
47
+ end
48
+
49
+ it 'should handle negation' do
50
+ @x.must_not_be.in @range_domain
51
+ @model.solve!
52
+ @x.should have_domain(@domain.to_a - @range_domain.to_a)
53
+ end
54
+
55
+ it_should_behave_like 'constraint with options'
56
+ end
@@ -0,0 +1,128 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/constraint_helper'
3
+
4
+ class ElementSampleProblem < Gecode::Model
5
+ attr :prices
6
+ attr :store
7
+ attr :price
8
+ attr :fixnum_prices
9
+
10
+ def initialize
11
+ prices = [17, 63, 45, 63]
12
+ @fixnum_prices = wrap_enum(prices)
13
+ @prices = int_var_array(4, *prices)
14
+ @store = int_var(0...prices.size)
15
+ @price = int_var(*prices)
16
+ branch_on wrap_enum([@store])
17
+ end
18
+ end
19
+
20
+ describe Gecode::Constraints::IntEnum::Element do
21
+ before do
22
+ @model = ElementSampleProblem.new
23
+ @prices = @model.prices
24
+ @price = @model.price
25
+ @store = @model.store
26
+ @fixnum_prices = @model.fixnum_prices
27
+
28
+ # For constraint option spec.
29
+ @invoke_options = lambda do |hash|
30
+ @prices[@store].must_be.greater_than(@price, hash)
31
+ @model.solve!
32
+ end
33
+ @expect_options = lambda do |strength, reif_var|
34
+ if reif_var.nil?
35
+ Gecode::Raw.should_receive(:element).once.with(@model.active_space,
36
+ an_instance_of(Gecode::Raw::IntVarArray),
37
+ an_instance_of(Gecode::Raw::IntVar),
38
+ an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
39
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
40
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR,
41
+ an_instance_of(Gecode::Raw::IntVar), strength)
42
+ else
43
+ Gecode::Raw.should_receive(:element).once.with(@model.active_space,
44
+ an_instance_of(Gecode::Raw::IntVarArray),
45
+ an_instance_of(Gecode::Raw::IntVar),
46
+ an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
47
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
48
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR,
49
+ an_instance_of(Gecode::Raw::IntVar),
50
+ an_instance_of(Gecode::Raw::BoolVar), strength)
51
+ end
52
+ end
53
+ end
54
+
55
+ Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
56
+ it "should translate #{relation} with variable right hand side" do
57
+ Gecode::Raw.should_receive(:element).once.with(@model.active_space,
58
+ an_instance_of(Gecode::Raw::IntVarArray),
59
+ an_instance_of(Gecode::Raw::IntVar),
60
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
61
+ unless type == Gecode::Raw::IRT_EQ
62
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
63
+ an_instance_of(Gecode::Raw::IntVar), type,
64
+ an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
65
+ end
66
+ @prices[@store].must.send(relation, @price)
67
+ @model.solve!
68
+ end
69
+ end
70
+
71
+ Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
72
+ it "should translate negated #{relation} with variable right hand side" do
73
+ Gecode::Raw.should_receive(:element).once.with(@model.active_space,
74
+ an_instance_of(Gecode::Raw::IntVarArray),
75
+ an_instance_of(Gecode::Raw::IntVar),
76
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
77
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
78
+ an_instance_of(Gecode::Raw::IntVar), type,
79
+ an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
80
+ @prices[@store].must_not.send(relation, @price)
81
+ @model.solve!
82
+ end
83
+ end
84
+
85
+ Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
86
+ it "should translate #{relation} with constant right hand side" do
87
+ Gecode::Raw.should_receive(:element).once.with(@model.active_space,
88
+ an_instance_of(Gecode::Raw::IntVarArray),
89
+ an_instance_of(Gecode::Raw::IntVar),
90
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
91
+ unless type == Gecode::Raw::IRT_EQ
92
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
93
+ an_instance_of(Gecode::Raw::IntVar), type, 5, an_instance_of(Fixnum))
94
+ end
95
+ @prices[@store].must.send(relation, 5)
96
+ @model.solve!
97
+ end
98
+ end
99
+
100
+ Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
101
+ it "should translate negated #{relation} with constant right hand side" do
102
+ Gecode::Raw.should_receive(:element).once.with(@model.active_space,
103
+ an_instance_of(Gecode::Raw::IntVarArray),
104
+ an_instance_of(Gecode::Raw::IntVar),
105
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
106
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
107
+ an_instance_of(Gecode::Raw::IntVar), type, 5, an_instance_of(Fixnum))
108
+ @prices[@store].must_not.send(relation, 5)
109
+ @model.solve!
110
+ end
111
+ end
112
+
113
+ it 'should not disturb normal array access' do
114
+ @fixnum_prices[2].should_not be_nil
115
+ @prices[2].should_not be_nil
116
+ end
117
+
118
+ it 'should handle fixnum enums as enumeration' do
119
+ @fixnum_prices[@store].must == @fixnum_prices[2]
120
+ @model.solve!.store.val.should equal(2)
121
+ end
122
+
123
+ it 'should raise error on right hand sides of the wrong type' do
124
+ lambda{ @prices[@store].must == 'hello' }.should raise_error(TypeError)
125
+ end
126
+
127
+ it_should_behave_like 'constraint with options'
128
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/constraint_helper'
3
+
4
+ describe Gecode::Constraints::IntEnum::Equality do
5
+ before do
6
+ @model = Gecode::Model.new
7
+ @vars = @model.int_var_array(4, -2..2)
8
+ @invoke_options = lambda do |hash|
9
+ @vars.must_be.equal(hash)
10
+ @model.solve!
11
+ end
12
+ @expect_options = lambda do |strength, reif_var|
13
+ Gecode::Raw.should_receive(:eq).once.with(@model.active_space,
14
+ anything, strength)
15
+ end
16
+ end
17
+
18
+ it 'should translate equality constraints' do
19
+ @expect_options.call(Gecode::Raw::ICL_DEF, nil)
20
+ @invoke_options.call({})
21
+ @vars.must_be.equal
22
+ end
23
+
24
+ it 'should not allow negation' do
25
+ lambda{ @vars.must_not_be.equal }.should raise_error(
26
+ Gecode::MissingConstraintError)
27
+ end
28
+
29
+ it_should_behave_like 'constraint with strength option'
30
+ end
@@ -0,0 +1,166 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/constraint_helper'
3
+
4
+ class LinearSampleProblem < Gecode::Model
5
+ attr :x
6
+ attr :y
7
+ attr :z
8
+
9
+ def initialize(x_dom, y_dom, z_dom)
10
+ @x = self.int_var(x_dom)
11
+ @y = self.int_var(y_dom)
12
+ @z = self.int_var(z_dom)
13
+ branch_on wrap_enum([@x, @y, @z])
14
+ end
15
+ end
16
+
17
+ describe Gecode::Constraints::Int::Linear do
18
+ before do
19
+ @x_dom = 0..2
20
+ @y_dom = -3..3
21
+ @z_dom = 0..10
22
+ @model = LinearSampleProblem.new(@x_dom, @y_dom, @z_dom)
23
+ @x = @model.x
24
+ @y = @model.y
25
+ @z = @model.z
26
+
27
+ # For constraint option spec.
28
+ @invoke_options = lambda do |hash|
29
+ (@x + @y).must_be.greater_than(@z, hash)
30
+ @model.solve!
31
+ end
32
+ @expect_options = lambda do |strength, reif_var|
33
+ # TODO: this is hard to spec from this level.
34
+ end
35
+ end
36
+
37
+ it 'should handle addition with a variable' do
38
+ (@x + @y).must == 0
39
+ sol = @model.solve!
40
+ x = sol.x.val
41
+ y = sol.y.val
42
+ (x + y).should be_zero
43
+ end
44
+
45
+ it 'should handle addition with multiple variables' do
46
+ (@x + @y + @z).must == 0
47
+ sol = @model.solve!
48
+ x = sol.x.val
49
+ y = sol.y.val
50
+ z = sol.z.val
51
+ (x + y + z).should be_zero
52
+ end
53
+
54
+ it 'should handle subtraction with a variable' do
55
+ (@x - @y).must == 0
56
+ sol = @model.solve!
57
+ x = sol.x.val
58
+ y = sol.y.val
59
+ (x - y).should be_zero
60
+ end
61
+
62
+ it 'should handle non-zero constants as right hand side' do
63
+ (@x + @y).must == 1
64
+ sol = @model.solve!
65
+ x = sol.x.val
66
+ y = sol.y.val
67
+ (x + y).should equal(1)
68
+ end
69
+
70
+ it 'should handle variables as right hand side' do
71
+ (@x + @y).must == @z
72
+ sol = @model.solve!
73
+ x = sol.x.val
74
+ y = sol.y.val
75
+ z = sol.z.val
76
+ (x + y).should equal(z)
77
+ end
78
+
79
+ it 'should handle linear expressions as right hand side' do
80
+ (@x + @y).must == @z + @y
81
+ sol = @model.solve!
82
+ x = sol.x.val
83
+ y = sol.y.val
84
+ z = sol.z.val
85
+ (x + y).should equal(z + y)
86
+ end
87
+
88
+ it 'should raise error on invalid right hand sides' do
89
+ lambda{ ((@x + @y).must == 'z') }.should raise_error(TypeError)
90
+ end
91
+
92
+ it 'should handle coefficients other than 1' do
93
+ (@x * 2 + @y).must == 0
94
+ sol = @model.solve!
95
+ x = sol.x.val
96
+ y = sol.y.val
97
+ (2*x + y).should equal(0)
98
+ end
99
+
100
+ it 'should handle addition with constants' do
101
+ (@y + 2).must == 1
102
+ sol = @model.solve!
103
+ y = sol.y.val
104
+ (y + 2).should equal(1)
105
+ end
106
+
107
+ it 'should handle subtraction with a constant' do
108
+ (@x - 2).must == 0
109
+ sol = @model.solve!
110
+ x = sol.x.val
111
+ (x - 2).should be_zero
112
+ end
113
+
114
+ it 'should a single variable as left hande side' do
115
+ @x.must == @y + @z
116
+ sol = @model.solve!
117
+ x = sol.x.val
118
+ y = sol.y.val
119
+ z = sol.z.val
120
+ x.should equal(y + z)
121
+ end
122
+
123
+ it 'should handle parenthesis' do
124
+ (@x - (@y + @z)).must == 1
125
+ sol = @model.solve!
126
+ x = sol.x.val
127
+ y = sol.y.val
128
+ z = sol.z.val
129
+ (x - (y + z)).should equal(1)
130
+ end
131
+
132
+ it 'should handle multiplication of parenthesis' do
133
+ (((@x + @y*10)*10 + @z)*10).must == 0
134
+ sol = @model.solve!
135
+ x = sol.x.val
136
+ y = sol.y.val
137
+ z = sol.z.val
138
+ (((x + y*10)*10 + z)*10).should equal(0)
139
+ end
140
+
141
+ relations = ['>', '>=', '<', '<=', '==']
142
+
143
+ relations.each do |relation|
144
+ it "should handle #{relation} with constant integers" do
145
+ (@x + @y).must.send(relation, 1)
146
+ sol = @model.solve!
147
+ sol.should_not be_nil
148
+ (sol.x.val + sol.y.val).should.send(relation, 1)
149
+ end
150
+ end
151
+
152
+ relations.each do |relation|
153
+ it "should handle negated #{relation} with constant integers" do
154
+ (@x + @y).must_not.send(relation, 1)
155
+ sol = @model.solve!
156
+ sol.should_not be_nil
157
+ (sol.x.val + sol.y.val).should_not.send(relation, 1)
158
+ end
159
+ end
160
+
161
+ it 'should not interfere with other defined multiplication methods' do
162
+ (@x * :foo).should be_nil
163
+ end
164
+
165
+ it_should_behave_like 'constraint with options'
166
+ end
@@ -0,0 +1,92 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ class ReifSugarSampleProblem < Gecode::Model
4
+ attr :x
5
+ attr :y
6
+ attr :z
7
+
8
+ def initialize
9
+ @x = int_var(0..1)
10
+ @y = int_var(1..2)
11
+ @z = int_var(3..4)
12
+ branch_on wrap_enum([@x, @y, @z])
13
+ end
14
+ end
15
+
16
+ describe Gecode::Constraints::ReifiableConstraint do
17
+ before do
18
+ @model = ReifSugarSampleProblem.new
19
+ @x = @model.x
20
+ @y = @model.y
21
+ @z = @model.z
22
+ end
23
+
24
+ it 'should fail disjunctions if neither side can be satisfied' do
25
+ (@x.must == 3) | (@y.must == 3)
26
+ @model.solve!.should be_nil
27
+ end
28
+
29
+ it 'should translate disjunctions' do
30
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
31
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR, 0,
32
+ an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF)
33
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
34
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_EQ, 3,
35
+ an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF)
36
+ (@x.must > 0) | (@y.must == 3)
37
+ sol = @model.solve!
38
+ end
39
+
40
+ it 'should solve disjunctions' do
41
+ (@x.must > 0) | (@y.must == 3)
42
+ sol = @model.solve!
43
+ sol.should_not be_nil
44
+ sol.x.should have_domain([1])
45
+ end
46
+
47
+ it 'should fail conjunctions if one side can\'t be satisfied' do
48
+ (@x.must > 3) & (@y.must == 3)
49
+ @model.solve!.should be_nil
50
+ end
51
+
52
+ it 'should translate conjunctions' do
53
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
54
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR, 0,
55
+ an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF)
56
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
57
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_EQ, 2,
58
+ an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF)
59
+ (@x.must > 0) & (@y.must == 2)
60
+ sol = @model.solve!
61
+ end
62
+
63
+ it 'should solve conjunctions' do
64
+ (@x.must > 0) & (@y.must == 2)
65
+ sol = @model.solve!
66
+ sol.should_not be_nil
67
+ sol.x.should have_domain([1])
68
+ sol.y.should have_domain([2])
69
+ end
70
+
71
+ it 'should handle the same variable being used multiple times' do
72
+ (@z.must == 4) | (@z.must == 4)
73
+ sol = @model.solve!
74
+ sol.should_not be_nil
75
+ sol.z.should have_domain([4])
76
+ end
77
+
78
+ it 'should handle nested operations' do
79
+ ((@x.must > 3) & (@y.must == 2)) | (@z.must == 4) | (
80
+ (@x.must == 0) & (@z.must == 4))
81
+ sol = @model.solve!
82
+ sol.should_not be_nil
83
+ sol.x.should have_domain([0])
84
+ sol.z.should have_domain([4])
85
+ end
86
+
87
+ it 'should handle negations' do
88
+ (@z.must_not == 4) & (@z.must == 4)
89
+ sol = @model.solve!
90
+ sol.should be_nil
91
+ end
92
+ end
@@ -0,0 +1,72 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/constraint_helper'
3
+
4
+ describe Gecode::Constraints::Int::Linear, ' (simple ones)' do
5
+ before do
6
+ @model = Gecode::Model.new
7
+ @x = @model.int_var(1..2)
8
+ @int = 4
9
+ @y = @model.int_var(1..2)
10
+
11
+ # For constraint option spec.
12
+ @invoke_options = lambda do |hash|
13
+ @x.must_be.greater_than(3, hash)
14
+ @model.solve!
15
+ end
16
+ @expect_options = lambda do |strength, reif_var|
17
+ if reif_var.nil?
18
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
19
+ anything, Gecode::Raw::IRT_GR, anything,
20
+ strength)
21
+ else
22
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
23
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR, anything,
24
+ an_instance_of(Gecode::Raw::BoolVar), strength)
25
+ end
26
+ end
27
+ end
28
+
29
+ Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
30
+ it "should translate #{relation} with constant to simple relation" do
31
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
32
+ an_instance_of(Gecode::Raw::IntVar), type, @int, Gecode::Raw::ICL_DEF)
33
+ @x.must.send(relation, @int)
34
+ @model.solve!
35
+ end
36
+ end
37
+
38
+ Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
39
+ it "should translate negated #{relation} with constant to simple relation" do
40
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
41
+ an_instance_of(Gecode::Raw::IntVar), type, @int, Gecode::Raw::ICL_DEF)
42
+ @x.must_not.send(relation, @int)
43
+ @model.solve!
44
+ end
45
+ end
46
+
47
+ Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
48
+ it "should translate #{relation} with variables to simple relation" do
49
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
50
+ an_instance_of(Gecode::Raw::IntVar), type,
51
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
52
+ @x.must.send(relation, @y)
53
+ @model.solve!
54
+ end
55
+ end
56
+
57
+ Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
58
+ it "should translate negated #{relation} with variable to simple relation" do
59
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
60
+ an_instance_of(Gecode::Raw::IntVar), type,
61
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::ICL_DEF)
62
+ @x.must_not.send(relation, @y)
63
+ @model.solve!
64
+ end
65
+ end
66
+
67
+ it 'should raise error on arguments of the wrong type' do
68
+ lambda{ @x.must == 'hello' }.should raise_error(TypeError)
69
+ end
70
+
71
+ it_should_behave_like 'constraint with options'
72
+ end