gecoder 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/CHANGES +11 -0
  2. data/README +12 -1
  3. data/example/example_helper.rb +1 -0
  4. data/example/magic_sequence.rb +43 -0
  5. data/example/queens.rb +43 -0
  6. data/example/raw_bindings.rb +42 -0
  7. data/example/send_more_money.rb +43 -0
  8. data/example/sudoku.rb +65 -0
  9. data/ext/missing.cpp +15 -21
  10. data/ext/missing.h +14 -20
  11. data/ext/vararray.cpp +14 -20
  12. data/ext/vararray.h +18 -22
  13. data/lib/gecoder/bindings/bindings.rb +1979 -1969
  14. data/lib/gecoder/interface/binding_changes.rb +123 -2
  15. data/lib/gecoder/interface/constraints/bool/boolean.rb +80 -65
  16. data/lib/gecoder/interface/constraints/bool_enum/boolean.rb +59 -0
  17. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +8 -0
  18. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +42 -0
  19. data/lib/gecoder/interface/constraints/int/arithmetic.rb +21 -44
  20. data/lib/gecoder/interface/constraints/int/domain.rb +6 -4
  21. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +18 -44
  22. data/lib/gecoder/interface/constraints/int_enum/count.rb +3 -18
  23. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +4 -16
  24. data/lib/gecoder/interface/constraints/int_enum/element.rb +9 -20
  25. data/lib/gecoder/interface/constraints/int_var_constraints.rb +28 -0
  26. data/lib/gecoder/interface/constraints/set/cardinality.rb +56 -0
  27. data/lib/gecoder/interface/constraints/set/domain.rb +66 -0
  28. data/lib/gecoder/interface/constraints/set/relation.rb +125 -0
  29. data/lib/gecoder/interface/constraints/set_var_constraints.rb +37 -0
  30. data/lib/gecoder/interface/constraints.rb +229 -65
  31. data/lib/gecoder/interface/enum_wrapper.rb +42 -11
  32. data/lib/gecoder/interface/model.rb +75 -0
  33. data/lib/gecoder/interface/search.rb +4 -9
  34. data/lib/gecoder/interface/variables.rb +36 -2
  35. data/lib/gecoder/version.rb +1 -1
  36. data/specs/bool_var.rb +58 -0
  37. data/specs/constraints/arithmetic.rb +91 -90
  38. data/specs/constraints/bool_enum.rb +130 -0
  39. data/specs/constraints/boolean.rb +95 -2
  40. data/specs/constraints/cardinality.rb +127 -0
  41. data/specs/constraints/constraint_helper.rb +91 -0
  42. data/specs/constraints/constraints.rb +31 -0
  43. data/specs/constraints/element.rb +43 -72
  44. data/specs/constraints/{domain.rb → int_domain.rb} +4 -0
  45. data/specs/constraints/{relation.rb → int_relation.rb} +0 -0
  46. data/specs/constraints/set_domain.rb +165 -0
  47. data/specs/constraints/set_relation.rb +181 -0
  48. data/specs/enum_wrapper.rb +13 -2
  49. data/specs/int_var.rb +33 -1
  50. data/specs/model.rb +80 -0
  51. data/specs/set_var.rb +39 -0
  52. data/specs/spec_helper.rb +35 -0
  53. data/specs/tmp +11 -124
  54. data/tasks/distribution.rake +1 -1
  55. data/vendor/rust/rust/class.rb +10 -10
  56. data/vendor/rust/rust/constants.rb +1 -1
  57. data/vendor/rust/rust/function.rb +5 -5
  58. data/vendor/rust/rust/type.rb +1 -1
  59. data/vendor/rust/test/constants.rb +1 -0
  60. data/vendor/rust/test/cppclass.cc +5 -0
  61. data/vendor/rust/test/cppclass.hh +4 -0
  62. data/vendor/rust/test/lib/extension-test.rb +1 -1
  63. data/vendor/rust/test/operators.cc +41 -0
  64. data/vendor/rust/test/operators.hh +39 -0
  65. data/vendor/rust/test/operators.rb +39 -0
  66. data/vendor/rust/test/test-cwrapper.rb +3 -0
  67. data/vendor/rust/test/test-operators.rb +42 -0
  68. metadata +31 -4
@@ -45,4 +45,95 @@ describe 'constraint with options', :shared => true do
45
45
  end
46
46
 
47
47
  it_should_behave_like 'constraint with strength option'
48
+ end
49
+
50
+ # This requires that the constraint spec has the instance variable
51
+ # @expect_relation which takes a relation and right hand side as arguments and
52
+ # sets up the corresponding expectations. It also requires @invoke_relation and
53
+ # @invoke_negated_relation with the same arguments. The spec is also required to
54
+ # provide an int var @target.
55
+ describe 'composite constraint', :shared => true do
56
+ Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
57
+ it "should translate #{relation} with constant target" do
58
+ @expect_relation.call(type, 1, false)
59
+ @invoke_relation.call(relation, 1, false)
60
+ end
61
+ end
62
+
63
+ Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
64
+ it "should translate #{relation} with variable target" do
65
+ @expect_relation.call(type, @target, false)
66
+ @invoke_relation.call(relation, @target, false)
67
+ end
68
+ end
69
+
70
+ Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
71
+ it "should translate negated #{relation} with constant target" do
72
+ @expect_relation.call(type, 1, true)
73
+ @invoke_relation.call(relation, 1, true)
74
+ end
75
+ end
76
+
77
+ Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
78
+ it "should translate negated #{relation} with variable target" do
79
+ @expect_relation.call(type, @target, true)
80
+ @invoke_relation.call(relation, @target, true)
81
+ end
82
+ end
83
+
84
+ it 'should raise error if the target is of the wrong type' do
85
+ lambda do
86
+ @invoke_relation.call(:==, 'hello', false)
87
+ end.should raise_error(TypeError)
88
+ end
89
+ end
90
+
91
+ # Requires @invoke_options and @model.
92
+ describe 'non-reifiable set constraint', :shared => true do
93
+ it 'should not accept strength option' do
94
+ lambda do
95
+ @invoke_options.call(:strength => :default)
96
+ end.should raise_error(ArgumentError)
97
+ end
98
+
99
+ it 'should not accept reification option' do
100
+ bool = @model.bool_var
101
+ lambda do
102
+ @invoke_options.call(:reify => bool)
103
+ end.should raise_error(ArgumentError)
104
+ end
105
+ end
106
+
107
+ # Requires @invoke_options, @expect_options and @model.
108
+ describe 'reifiable set constraint', :shared => true do
109
+ it 'should not accept strength option' do
110
+ lambda do
111
+ @invoke_options.call(:strength => :default)
112
+ end.should raise_error(ArgumentError)
113
+ end
114
+
115
+ it 'should accept reification option' do
116
+ bool = @model.bool_var
117
+ @expect_options.call(nil, bool)
118
+ @invoke_options.call(:reify => bool)
119
+ end
120
+ end
121
+
122
+ # Help methods for the GecodeR specs.
123
+ module GecodeR::Specs
124
+ module SetHelper
125
+ module_function
126
+
127
+ # Returns the arguments that should be used in a partial mock to expect the
128
+ # specified constant set (possibly an array of arguments).
129
+ def expect_constant_set(constant_set)
130
+ if constant_set.kind_of? Range
131
+ return constant_set.first, constant_set.last
132
+ elsif constant_set.kind_of? Fixnum
133
+ constant_set
134
+ else
135
+ an_instance_of(Gecode::Raw::IntSet)
136
+ end
137
+ end
138
+ end
48
139
  end
@@ -17,6 +17,18 @@ describe Gecode::Constraints::IntEnum::Expression do
17
17
  end
18
18
  end
19
19
 
20
+ describe Gecode::Constraints::Int::CompositeStub, ' (not subclassed)' do
21
+ before do
22
+ @con = Gecode::Constraints::Int::CompositeStub.new(Gecode::Model.new, {})
23
+ end
24
+
25
+ it 'should raise error when calling #constrain_equal' do
26
+ lambda do
27
+ @con.instance_eval{ constrain_equal(nil, {}) }
28
+ end.should raise_error(NoMethodError)
29
+ end
30
+ end
31
+
20
32
  describe Gecode::Constraints::Constraint, ' (not subclassed)' do
21
33
  before do
22
34
  @con = Gecode::Constraints::Constraint.new(Gecode::Model.new, {})
@@ -25,4 +37,23 @@ describe Gecode::Constraints::Constraint, ' (not subclassed)' do
25
37
  it 'should raise error when calling #post because it\'s not overridden' do
26
38
  lambda{ @con.post }.should raise_error(NoMethodError)
27
39
  end
40
+ end
41
+
42
+ describe Gecode::Constraints::Util do
43
+ it 'should raise error when giving incorrect set to #constant_set_to_params' do
44
+ lambda do
45
+ Gecode::Constraints::Util.constant_set_to_params('hello')
46
+ end.should raise_error(TypeError)
47
+ end
48
+ end
49
+
50
+ describe Gecode::Constraints::CompositeExpression do
51
+ it 'should raise error if a method doesn\'t exist' do
52
+ expression = Gecode::Constraints::CompositeExpression.new(
53
+ Gecode::Constraints::Int::Expression, Gecode::FreeIntVar,
54
+ Gecode::Model.new, {:lhs => nil, :negate => false}){}
55
+ lambda do
56
+ expression.this_method_does_not_exist
57
+ end.should raise_error(NoMethodError)
58
+ end
28
59
  end
@@ -21,92 +21,58 @@ describe Gecode::Constraints::IntEnum::Element do
21
21
  before do
22
22
  @model = ElementSampleProblem.new
23
23
  @prices = @model.prices
24
- @price = @model.price
24
+ @target = @price = @model.price
25
25
  @store = @model.store
26
26
  @fixnum_prices = @model.fixnum_prices
27
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|
28
+ # Creates an expectation corresponding to the specified input.
29
+ @expect = lambda do |element, relation, target, strength, reif_var, negated|
30
+ target = target.bind if target.respond_to? :bind
31
+ element = element.bind if element.respond_to? :bind
34
32
  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)
33
+ if !negated and relation == Gecode::Raw::IRT_EQ and
34
+ target.kind_of? Gecode::Raw::IntVar
35
+ Gecode::Raw.should_receive(:element).once.with(@model.active_space,
36
+ an_instance_of(Gecode::Raw::IntVarArray),
37
+ element, target, strength)
38
+ else
39
+ Gecode::Raw.should_receive(:element).once.with(@model.active_space,
40
+ an_instance_of(Gecode::Raw::IntVarArray),
41
+ element, an_instance_of(Gecode::Raw::IntVar), strength)
42
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
43
+ an_instance_of(Gecode::Raw::IntVar), relation, target, strength)
44
+ end
42
45
  else
43
46
  Gecode::Raw.should_receive(:element).once.with(@model.active_space,
44
47
  an_instance_of(Gecode::Raw::IntVarArray),
45
- an_instance_of(Gecode::Raw::IntVar),
46
- an_instance_of(Gecode::Raw::IntVar), an_instance_of(Fixnum))
48
+ element, an_instance_of(Gecode::Raw::IntVar), strength)
47
49
  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::IntVar), relation, target,
50
51
  an_instance_of(Gecode::Raw::BoolVar), strength)
51
52
  end
52
53
  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
54
 
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)
55
+ # For constraint option spec.
56
+ @invoke_options = lambda do |hash|
57
+ @prices[@store].must_be.greater_than(@price, hash)
81
58
  @model.solve!
82
59
  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))
60
+ @expect_options = lambda do |strength, reif_var|
61
+ @expect.call(@store, Gecode::Raw::IRT_GR, @price, strength, reif_var,
62
+ false)
63
+ end
64
+
65
+ # For composite spec.
66
+ @invoke_relation = lambda do |relation, target, negated|
67
+ if negated
68
+ @prices[@store].must_not.send(relation, target)
69
+ else
70
+ @prices[@store].must.send(relation, target)
94
71
  end
95
- @prices[@store].must.send(relation, 5)
96
72
  @model.solve!
97
73
  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!
74
+ @expect_relation = lambda do |relation, target, negated|
75
+ @expect.call(@store, relation, target, Gecode::Raw::ICL_DEF, nil, negated)
110
76
  end
111
77
  end
112
78
 
@@ -119,10 +85,15 @@ describe Gecode::Constraints::IntEnum::Element do
119
85
  @fixnum_prices[@store].must == @fixnum_prices[2]
120
86
  @model.solve!.store.val.should equal(2)
121
87
  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)
88
+
89
+ it 'should translate reification when using equality' do
90
+ bool_var = @model.bool_var
91
+ @expect.call(@store, Gecode::Raw::IRT_EQ, @target, Gecode::Raw::ICL_DEF,
92
+ bool_var, false)
93
+ @prices[@store].must_be.equal_to(@target, :reify => bool_var)
94
+ @model.solve!
125
95
  end
126
96
 
97
+ it_should_behave_like 'composite constraint'
127
98
  it_should_behave_like 'constraint with options'
128
99
  end
@@ -52,5 +52,9 @@ describe Gecode::Constraints::Int::Domain do
52
52
  @x.should have_domain(@domain.to_a - @range_domain.to_a)
53
53
  end
54
54
 
55
+ it 'should raise error if the right hand side is not an enumeration' do
56
+ lambda{ @x.must_be.in 'hello' }.should raise_error(TypeError)
57
+ end
58
+
55
59
  it_should_behave_like 'constraint with options'
56
60
  end
File without changes
@@ -0,0 +1,165 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/constraint_helper'
3
+
4
+ describe Gecode::Constraints::Set::Domain do
5
+ include GecodeR::Specs::SetHelper
6
+
7
+ before do
8
+ @model = Gecode::Model.new
9
+ @glb = [0]
10
+ @lub = 0..3
11
+ @set = @model.set_var(@glb, @lub)
12
+ @range = 0..1
13
+ @non_range = [0, 2]
14
+ @singleton = 0
15
+
16
+ @expect = lambda do |relation_type, rhs, reif_var, negated|
17
+ if reif_var.nil? and !negated
18
+ Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
19
+ @set.bind, relation_type, *expect_constant_set(rhs))
20
+ else
21
+ params = [@model.active_space, @set.bind, relation_type]
22
+ params << expect_constant_set(rhs)
23
+ params << an_instance_of(Gecode::Raw::BoolVar)
24
+ Gecode::Raw.should_receive(:dom).once.with(*params.flatten)
25
+ end
26
+ end
27
+
28
+ # For options spec.
29
+ @invoke_options = lambda do |hash|
30
+ @set.must_be.superset_of(@non_range, hash)
31
+ @model.solve!
32
+ end
33
+ @expect_options = lambda do |strength, reif_var|
34
+ @expect.call(Gecode::Raw::SRT_SUP, @non_range, reif_var, false)
35
+ end
36
+ end
37
+
38
+ Gecode::Constraints::Util::SET_RELATION_TYPES.each_pair do |relation, type|
39
+ next if relation == :==
40
+
41
+ it "should translate #{relation} with constant range to domain constraint" do
42
+ @expect.call(type, @range, nil, false)
43
+ @set.must.send(relation, @range)
44
+ @model.solve!
45
+ end
46
+
47
+ it "should translate #{relation} with constant non-range to domain constraint" do
48
+ @expect.call(type, @non_range, nil, false)
49
+ @set.must.send(relation, @non_range)
50
+ @model.solve!
51
+ end
52
+
53
+ it "should translate #{relation} with constant singleton to domain constraint" do
54
+ @expect.call(type, @singleton, nil, false)
55
+ @set.must.send(relation, @singleton)
56
+ @model.solve!
57
+ end
58
+
59
+ it "should translate negated #{relation} with constant range to domain constraint" do
60
+ @expect.call(type, @range, nil, true)
61
+ @set.must_not.send(relation, @range)
62
+ @model.solve!
63
+ end
64
+
65
+ it "should translate negated #{relation} with constant non-range to domain constraint" do
66
+ @expect.call(type, @non_range, nil, true)
67
+ @set.must_not.send(relation, @non_range)
68
+ @model.solve!
69
+ end
70
+
71
+ it "should translate negated #{relation} with constant singleton to domain constraint" do
72
+ @expect.call(type, @singleton, nil, true)
73
+ @set.must_not.send(relation, @singleton)
74
+ @model.solve!
75
+ end
76
+ end
77
+
78
+ it_should_behave_like 'reifiable set constraint'
79
+ end
80
+
81
+ describe Gecode::Constraints::Set::Domain, ' (equality)' do
82
+ include GecodeR::Specs::SetHelper
83
+
84
+ before do
85
+ @model = Gecode::Model.new
86
+ @glb = [0]
87
+ @lub = 0..3
88
+ @set = @model.set_var(@glb, @lub)
89
+ @range = 0..1
90
+ @non_range = [0, 2]
91
+ @singleton = 0
92
+
93
+ @expect = lambda do |relation_type, rhs, reif_var|
94
+ if reif_var.nil?
95
+ Gecode::Raw.should_receive(:dom).once.with(@model.active_space,
96
+ @set.bind, relation_type, *expect_constant_set(rhs))
97
+ else
98
+ params = [@model.active_space, @set.bind, relation_type]
99
+ params << expect_constant_set(rhs)
100
+ params << an_instance_of(Gecode::Raw::BoolVar)
101
+ Gecode::Raw.should_receive(:dom).once.with(*params.flatten)
102
+ end
103
+ end
104
+
105
+ # For options spec.
106
+ @invoke_options = lambda do |hash|
107
+ @set.must_be.equal_to(@non_range, hash)
108
+ @model.solve!
109
+ end
110
+ @expect_options = lambda do |strength, reif_var|
111
+ @expect.call(Gecode::Raw::SRT_EQ, @non_range, reif_var)
112
+ end
113
+ end
114
+
115
+ it 'should translate equality with constant range to domain constraint' do
116
+ @expect.call(Gecode::Raw::SRT_EQ, @range, nil)
117
+ @set.must == @range
118
+ @model.solve!
119
+ end
120
+
121
+ it 'should translate equality with constant non-range to domain constraint' do
122
+ @expect.call(Gecode::Raw::SRT_EQ, @non_range, nil)
123
+ @set.must == @non_range
124
+ @model.solve!
125
+ end
126
+
127
+ it 'should translate equality with constant singleton to domain constraint' do
128
+ @expect.call(Gecode::Raw::SRT_EQ, @singleton, nil)
129
+ @set.must == @singleton
130
+ @model.solve!
131
+ end
132
+
133
+ it 'should translate negated equality with constant range to domain constraint' do
134
+ @expect.call(Gecode::Raw::SRT_NQ, @range, nil)
135
+ @set.must_not == @range
136
+ @model.solve!
137
+ end
138
+
139
+ it 'should translate negated equality with constant non-range to domain constraint' do
140
+ @expect.call(Gecode::Raw::SRT_NQ, @non_range, nil)
141
+ @set.must_not == @non_range
142
+ @model.solve!
143
+ end
144
+
145
+ it 'should translate negated equality with constant singleton to domain constraint' do
146
+ @expect.call(Gecode::Raw::SRT_NQ, @singleton, nil)
147
+ @set.must_not == @singleton
148
+ @model.solve!
149
+ end
150
+
151
+ it 'should constrain the domain with equality' do
152
+ @set.must == @singleton
153
+ @model.solve!
154
+ @set.should be_assigned
155
+ @set.should include(@singleton)
156
+ @set.val_size.should == 1
157
+ end
158
+
159
+ it 'should constrain the domain with inequality' do
160
+ @set.must_not == @singleton
161
+ @model.solve!.should be_nil
162
+ end
163
+
164
+ it_should_behave_like 'reifiable set constraint'
165
+ end
@@ -0,0 +1,181 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/constraint_helper'
3
+
4
+ describe Gecode::Constraints::Set::Relation do
5
+ include GecodeR::Specs::SetHelper
6
+
7
+ before do
8
+ @model = Gecode::Model.new
9
+ @set = @model.set_var([0], 0..3)
10
+ @set2 = @model.set_var([1], 0..3)
11
+
12
+ @expect = lambda do |relation_type, rhs, reif_var, negated|
13
+ if reif_var.nil? and !negated
14
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
15
+ @set.bind, relation_type, @set2.bind)
16
+ else
17
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
18
+ @set.bind, relation_type, @set2.bind,
19
+ an_instance_of(Gecode::Raw::BoolVar))
20
+ end
21
+ end
22
+
23
+ # For options spec.
24
+ @invoke_options = lambda do |hash|
25
+ @set.must_be.superset_of(@set2, hash)
26
+ @model.solve!
27
+ end
28
+ @expect_options = lambda do |strength, reif_var|
29
+ @expect.call(Gecode::Raw::SRT_SUP, @set2, reif_var, false)
30
+ end
31
+ end
32
+
33
+ Gecode::Constraints::Util::SET_RELATION_TYPES.each_pair do |relation, type|
34
+ next if relation == :==
35
+
36
+ it "should translate #{relation} with set to relation constraint" do
37
+ @expect.call(type, @set2, nil, false)
38
+ @set.must.send(relation, @set2)
39
+ @model.solve!
40
+ end
41
+
42
+ it "should translate negated #{relation} with set to relation constraint" do
43
+ @expect.call(type, @set2, nil, true)
44
+ @set.must_not.send(relation, @set2)
45
+ @model.solve!
46
+ end
47
+ end
48
+ it_should_behave_like 'reifiable set constraint'
49
+ end
50
+
51
+ describe Gecode::Constraints::Set::Relation, ' (equality)' do
52
+ include GecodeR::Specs::SetHelper
53
+
54
+ before do
55
+ @model = Gecode::Model.new
56
+ @set = @model.set_var([0], 0..1)
57
+ @set2 = @model.set_var([1], 0..1)
58
+
59
+ @expect = lambda do |relation_type, rhs, reif_var|
60
+ if reif_var.nil?
61
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
62
+ @set.bind, relation_type, @set2.bind)
63
+ else
64
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
65
+ @set.bind, relation_type, @set2.bind,
66
+ an_instance_of(Gecode::Raw::BoolVar))
67
+ end
68
+ end
69
+
70
+ # For options spec.
71
+ @invoke_options = lambda do |hash|
72
+ @set.must_be.equal_to(@set2, hash)
73
+ @model.solve!
74
+ end
75
+ @expect_options = lambda do |strength, reif_var|
76
+ @expect.call(Gecode::Raw::SRT_EQ, @set2, reif_var)
77
+ end
78
+ end
79
+
80
+ it 'should translate equality with set to relation constraint' do
81
+ @expect.call(Gecode::Raw::SRT_EQ, @set2, nil)
82
+ @set.must == @set2
83
+ @model.solve!
84
+ end
85
+
86
+ it 'should translate negated equality with set to domain constraint' do
87
+ @expect.call(Gecode::Raw::SRT_NQ, @set2, nil)
88
+ @set.must_not == @set2
89
+ @model.solve!
90
+ end
91
+
92
+ it 'should constrain sets to be equality when not negated' do
93
+ @set.must == @set2
94
+ @model.solve!
95
+ @set.should have_bounds(0..1, 0..1)
96
+ @set2.should have_bounds(0..1, 0..1)
97
+ end
98
+
99
+ it 'should constrain sets to not be equal when negated' do
100
+ @set.must_not == @set2
101
+ union = @model.set_var([0, 1], [0, 1])
102
+ @set.must_not == union
103
+ @set2.must_not == union
104
+ @model.solve!
105
+ @set.should have_bounds([0], [0])
106
+ @set2.should have_bounds([1], [1])
107
+ end
108
+
109
+ it_should_behave_like 'reifiable set constraint'
110
+ end
111
+
112
+ describe Gecode::Constraints::Set::Relation, ' (elements)' do
113
+ include GecodeR::Specs::SetHelper
114
+
115
+ before do
116
+ @model = Gecode::Model.new
117
+ @set = @model.set_var([0], 0..2)
118
+ @int_var = @model.int_var(0..2)
119
+ @int_constant = 2
120
+ @model.branch_on @model.wrap_enum([@set])
121
+ @expect = lambda do |relation_type, rhs|
122
+ if rhs.kind_of? Fixnum
123
+ rhs = an_instance_of(Gecode::Raw::IntVar)
124
+ end
125
+ rhs = rhs.bind if rhs.respond_to? :bind
126
+ Gecode::Raw.should_receive(:rel).once.with(@model.active_space,
127
+ @set.bind, relation_type, rhs)
128
+ end
129
+
130
+ @invoke_options = lambda do |hash|
131
+ @set.elements.must_be.equal_to(@int_var, hash)
132
+ end
133
+ end
134
+
135
+ Gecode::Constraints::Util::RELATION_TYPES.each_pair do |relation, type|
136
+ it "should translate #{relation} with variable to relation constraint" do
137
+ @expect.call(type, @int_var)
138
+ @set.elements.must.send(relation, @int_var)
139
+ @model.solve!
140
+ end
141
+
142
+ it "should translate #{relation} with constant to relation constraint" do
143
+ @expect.call(type, @int_constant)
144
+ @set.elements.must.send(relation, @int_constant)
145
+ @model.solve!
146
+ end
147
+ end
148
+
149
+ Gecode::Constraints::Util::NEGATED_RELATION_TYPES.each_pair do |relation, type|
150
+ it "should translate negated #{relation} with variable to relation constraint" do
151
+ @expect.call(type, @int_var)
152
+ @set.elements.must_not.send(relation, @int_var)
153
+ @model.solve!
154
+ end
155
+
156
+ it "should translate negated #{relation} with constant to relation constraint" do
157
+ @expect.call(type, @int_constant)
158
+ @set.elements.must_not.send(relation, @int_constant)
159
+ @model.solve!
160
+ end
161
+ end
162
+
163
+ it 'should constrain the elements of the set' do
164
+ @set.elements.must <= @int_var
165
+ @int_var.must == 0
166
+ @model.solve!
167
+ @set.should be_assigned
168
+ @set.should include(0)
169
+ @set.should_not include(1,2)
170
+ end
171
+
172
+ it 'should constrain the elements of the set (constant parameter)' do
173
+ @set.elements.must <= 0
174
+ @model.solve!
175
+ @set.should be_assigned
176
+ @set.should include(0)
177
+ @set.should_not include(1,2)
178
+ end
179
+
180
+ it_should_behave_like 'non-reifiable set constraint'
181
+ end
@@ -80,11 +80,22 @@ end
80
80
  describe Gecode::BoolEnumMethods do
81
81
  before do
82
82
  @model = Gecode::Model.new
83
- @int_enum = @model.bool_var_array(3)
83
+ @bool_enum = @model.bool_var_array(3)
84
84
  end
85
85
 
86
86
  it 'should convert to a bool var array' do
87
- @int_enum.to_bool_var_array.should be_kind_of(Gecode::Raw::BoolVarArray)
87
+ @bool_enum.to_bool_var_array.should be_kind_of(Gecode::Raw::BoolVarArray)
88
+ end
89
+ end
90
+
91
+ describe Gecode::SetEnumMethods do
92
+ before do
93
+ @model = Gecode::Model.new
94
+ @set_enum = @model.set_var_array(3, [0], 0..1)
95
+ end
96
+
97
+ it 'should convert to a set var array' do
98
+ @set_enum.to_set_var_array.should be_kind_of(Gecode::Raw::SetVarArray)
88
99
  end
89
100
  end
90
101