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,160 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
2
- require File.dirname(__FILE__) + '/constraint_helper'
3
-
4
- class BoolEnumSampleProblem < Gecode::Model
5
- attr :bools
6
- attr :b1
7
- attr :b2
8
-
9
- def initialize
10
- @bools = bool_var_array(4)
11
- @b1 = bool_var
12
- @b2 = bool_var
13
- branch_on @bools
14
- branch_on wrap_enum([@b1, @b2])
15
- end
16
- end
17
-
18
- # Expects @stub, which contains the started constraint and @compute_result
19
- # which computes whether the left hand side is true or not.
20
- describe 'bool enum relation constraint', :shared => true do
21
- it 'should handle being constrained to be true' do
22
- @stub.must_be.true
23
- @model.solve!
24
- @compute_result.call.should be_true
25
- end
26
-
27
- it 'should handle being constrained to be negated true' do
28
- @stub.must_not_be.true
29
- @model.solve!
30
- @compute_result.call.should_not be_true
31
- end
32
-
33
- it 'should handle being constrained to be false' do
34
- @stub.must_be.false
35
- @model.solve!
36
- @compute_result.call.should_not be_true
37
- end
38
-
39
- it 'should handle being constrained to be negated false' do
40
- @stub.must_not_be.false
41
- @model.solve!
42
- @compute_result.call.should be_true
43
- end
44
-
45
- it 'should handle being constrained to be equal to a variable' do
46
- @stub.must_be == @b1
47
- @model.solve!
48
- @compute_result.call.should == @b1.value
49
- end
50
-
51
- it 'should handle being constrained to not be equal to a variable' do
52
- @stub.must_not_be == @b1
53
- @model.solve!
54
- @compute_result.call.should_not == @b1.value
55
- end
56
-
57
- it 'should handle being constrained to be equal to be a nested expression' do
58
- @stub.must_be == (@b1 | @b2) & @b1
59
- @model.solve!
60
- @compute_result.call.should == (@b1.value | @b2.value) & @b1.value
61
- end
62
-
63
- it 'should handle being constrained to not be equal to be a nested expression' do
64
- @stub.must_not_be == (@b1 | @b2) & @b1
65
- @model.solve!
66
- @compute_result.call.should_not == (@b1.value | @b2.value) & @b1.value
67
- end
68
- end
69
-
70
- describe Gecode::Constraints::BoolEnum::Relation, ' (conjunction)' do
71
- before do
72
- @model = BoolEnumSampleProblem.new
73
- @bools = @model.bools
74
- @b1 = @model.b1
75
- @b2 = @model.b2
76
-
77
- # For constraint option spec.
78
- @invoke_options = lambda do |hash|
79
- @bools.conjunction.must.equal(@b1, hash)
80
- @model.solve!
81
- end
82
- @expect_options = option_expectation do |strength, kind, reif_var|
83
- @model.allow_space_access do
84
- if reif_var.nil?
85
- Gecode::Raw.should_receive(:rel).once.with(
86
- an_instance_of(Gecode::Raw::Space),
87
- Gecode::Raw::BOT_AND,
88
- an_instance_of(Gecode::Raw::BoolVarArray),
89
- an_instance_of(Gecode::Raw::BoolVar),
90
- strength, kind)
91
- else
92
- Gecode::Raw.should_receive(:rel).once.with(
93
- an_instance_of(Gecode::Raw::Space),
94
- an_instance_of(Gecode::Raw::BoolVar),
95
- anything,
96
- an_instance_of(Gecode::Raw::BoolVar),
97
- anything, anything)
98
- Gecode::Raw.should_receive(:rel).once.with(
99
- an_instance_of(Gecode::Raw::Space),
100
- Gecode::Raw::BOT_AND,
101
- an_instance_of(Gecode::Raw::BoolVarArray),
102
- reif_var, strength, kind)
103
- end
104
- end
105
- end
106
-
107
- # For bool enum spec.
108
- @stub = @bools.conjunction
109
- @compute_result = lambda{ @bools.all?{ |b| b.value } }
110
- end
111
-
112
- it_should_behave_like 'bool enum relation constraint'
113
- it_should_behave_like 'reifiable constraint'
114
- end
115
-
116
- describe Gecode::Constraints::BoolEnum::Relation, ' (disjunction)' do
117
- before do
118
- @model = BoolEnumSampleProblem.new
119
- @bools = @model.bools
120
- @b1 = @model.b1
121
- @b2 = @model.b2
122
-
123
- # For constraint option spec.
124
- @invoke_options = lambda do |hash|
125
- @bools.disjunction.must.equal(@b1, hash)
126
- @model.solve!
127
- end
128
- @expect_options = option_expectation do |strength, kind, reif_var|
129
- @model.allow_space_access do
130
- if reif_var.nil?
131
- Gecode::Raw.should_receive(:rel).once.with(
132
- an_instance_of(Gecode::Raw::Space),
133
- Gecode::Raw::BOT_OR,
134
- an_instance_of(Gecode::Raw::BoolVarArray),
135
- an_instance_of(Gecode::Raw::BoolVar),
136
- strength, kind)
137
- else
138
- Gecode::Raw.should_receive(:rel).once.with(
139
- an_instance_of(Gecode::Raw::Space),
140
- an_instance_of(Gecode::Raw::BoolVar),
141
- anything,
142
- an_instance_of(Gecode::Raw::BoolVar),
143
- anything, anything)
144
- Gecode::Raw.should_receive(:rel).once.with(
145
- an_instance_of(Gecode::Raw::Space),
146
- Gecode::Raw::BOT_OR,
147
- an_instance_of(Gecode::Raw::BoolVarArray),
148
- reif_var, strength, kind)
149
- end
150
- end
151
- end
152
-
153
- # For bool enum spec.
154
- @stub = @bools.disjunction
155
- @compute_result = lambda{ @bools.any?{ |b| b.value } }
156
- end
157
-
158
- it_should_behave_like 'bool enum relation constraint'
159
- it_should_behave_like 'reifiable constraint'
160
- end
@@ -1,157 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
2
- require File.dirname(__FILE__) + '/constraint_helper'
3
-
4
- describe Gecode::Constraints::Set::Cardinality, ' (range)' do
5
- before do
6
- @model = Gecode::Model.new
7
- @set = @model.set_var([], 0..10)
8
- @model.branch_on @model.wrap_enum([@set])
9
- @range = 1..2
10
- @three_dot_range = 1...2
11
-
12
- @invoke_options = lambda do |hash|
13
- @set.size.must_be.in(@range, hash)
14
- end
15
-
16
- @invoke = lambda do |rhs|
17
- @set.size.must_be.in(rhs)
18
- @model.solve!
19
- end
20
- @expect = lambda do |rhs|
21
- @model.allow_space_access do
22
- Gecode::Raw.should_receive(:cardinality).once.with(
23
- an_instance_of(Gecode::Raw::Space),
24
- an_instance_of(Gecode::Raw::SetVar), rhs.first, rhs.last)
25
- end
26
- end
27
- end
28
-
29
- it 'should translate cardinality constraints with ranges' do
30
- @expect.call(@range)
31
- @invoke.call(@range)
32
- end
33
-
34
- it 'should translate cardinality constraints with three dot range domains' do
35
- @expect.call(@three_dot_range)
36
- @invoke.call(@three_dot_range)
37
- end
38
-
39
- it 'should constrain the cardinality of a set' do
40
- @set.size.must_be.in @range
41
- @model.solve!
42
- @range.should include(@set.value.size)
43
- end
44
-
45
- it 'should raise error if the right hand side is not a range' do
46
- lambda{ @set.size.must_be.in 'hello' }.should raise_error(TypeError)
47
- end
48
-
49
- it 'should not shadow the integer variable domain constrain' do
50
- Gecode::Raw.should_receive(:dom).with(
51
- an_instance_of(Gecode::Raw::Space),
52
- an_instance_of(Gecode::Raw::IntVar), 0, 11, Gecode::Raw::ICL_DEF,
53
- Gecode::Raw::PK_DEF)
54
- Gecode::Raw.should_receive(:dom).with(
55
- an_instance_of(Gecode::Raw::Space),
56
- an_instance_of(Gecode::Raw::IntVar), an_instance_of(Gecode::Raw::IntSet),
57
- an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF,
58
- Gecode::Raw::PK_DEF)
59
- @set.size.must_not_be.in [1,3]
60
- @model.solve!
61
- end
62
-
63
- it_should_behave_like 'non-reifiable set constraint'
64
- end
65
-
66
- describe Gecode::Constraints::Set::Cardinality, ' (composite)' do
67
- before do
68
- @model = Gecode::Model.new
69
- @set = @model.set_var([], 0..10)
70
- @target = @var = @model.int_var(0..11)
71
- @model.branch_on @model.wrap_enum([@set])
72
- @model.branch_on @model.wrap_enum([@var])
73
-
74
- @invoke = lambda do |rhs|
75
- @set.size.must == rhs
76
- @model.solve!
77
- end
78
- @expect = lambda do |relation, rhs, strength, kind, reif_var, negated|
79
- @model.allow_space_access do
80
- rhs = an_instance_of(Gecode::Raw::IntVar) if rhs.respond_to? :bind
81
- if reif_var.nil?
82
- if !negated and relation == Gecode::Raw::IRT_EQ and
83
- !rhs.kind_of? Fixnum
84
- Gecode::Raw.should_receive(:cardinality).once.with(
85
- an_instance_of(Gecode::Raw::Space),
86
- an_instance_of(Gecode::Raw::SetVar), rhs)
87
- Gecode::Raw.should_receive(:rel).exactly(0).times
88
- else
89
- Gecode::Raw.should_receive(:cardinality).once.with(
90
- an_instance_of(Gecode::Raw::Space),
91
- an_instance_of(Gecode::Raw::SetVar),
92
- an_instance_of(Gecode::Raw::IntVar))
93
- Gecode::Raw.should_receive(:rel).once.with(
94
- an_instance_of(Gecode::Raw::Space),
95
- an_instance_of(Gecode::Raw::IntVar), relation, rhs,
96
- strength, kind)
97
- end
98
- else
99
- Gecode::Raw.should_receive(:cardinality).once.with(
100
- an_instance_of(Gecode::Raw::Space),
101
- an_instance_of(Gecode::Raw::SetVar),
102
- an_instance_of(Gecode::Raw::IntVar))
103
- Gecode::Raw.should_receive(:rel).once.with(
104
- an_instance_of(Gecode::Raw::Space),
105
- an_instance_of(Gecode::Raw::IntVar), relation, rhs,
106
- an_instance_of(Gecode::Raw::BoolVar),
107
- strength, kind)
108
- end
109
- end
110
- end
111
-
112
- # For composite spec.
113
- @invoke_relation = lambda do |relation, target, negated|
114
- if negated
115
- @set.size.must_not.send(relation, target)
116
- else
117
- @set.size.must.send(relation, target)
118
- end
119
- @model.solve!
120
- end
121
- @expect_relation = lambda do |relation, target, negated|
122
- @expect.call(relation, target, Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF,
123
- nil, negated)
124
- end
125
-
126
- # For options spec.
127
- @invoke_options = lambda do |hash|
128
- @set.size.must_be.less_than_or_equal_to(17, hash)
129
- @model.solve!
130
- end
131
- @expect_options = option_expectation do |strength, kind, reif_var|
132
- @expect.call(Gecode::Raw::IRT_LQ, 17, strength, kind, reif_var, false)
133
- end
134
- end
135
-
136
- it 'should constrain the cardinality of a set' do
137
- @set.size.must == @var
138
- @model.solve!
139
- @set.value.size.should == @var.value
140
- end
141
-
142
- it 'should constrain the cardinality of a set (2)' do
143
- @set.size.must == 2
144
- @model.solve!.should_not be_nil
145
- @set.value.size.should == 2
146
- end
147
-
148
- it 'should constrain the cardinality of a set (3)' do
149
- @set.size.must == @var
150
- @var.must == 2
151
- @model.solve!
152
- @set.value.size.should == 2
153
- end
154
-
155
- it_should_behave_like 'reifiable constraint'
156
- it_should_behave_like 'composite constraint'
157
- end
@@ -1,454 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
2
- require File.dirname(__FILE__) + '/constraint_helper'
3
-
4
- class ChannelSampleProblem < Gecode::Model
5
- attr :elements
6
- attr :positions
7
- attr :sets
8
-
9
- def initialize
10
- @elements = int_var_array(4, 0..3)
11
- @elements.must_be.distinct
12
- @positions = int_var_array(4, 0..3)
13
- @positions.must_be.distinct
14
- @sets = set_var_array(4, [], 0..3)
15
- branch_on @positions
16
- end
17
- end
18
-
19
- class BoolChannelSampleProblem < Gecode::Model
20
- attr :bool_enum
21
- attr :bool
22
- attr :int
23
-
24
- def initialize
25
- @bool_enum = bool_var_array(4)
26
- @int = int_var(0..3)
27
- @bool = bool_var
28
-
29
- branch_on @int
30
- end
31
- end
32
-
33
- class SetChannelSampleProblem < Gecode::Model
34
- attr :bool_enum
35
- attr :set
36
-
37
- def initialize
38
- @bool_enum = bool_var_array(4)
39
- @set = set_var([], 0..3)
40
-
41
- branch_on @bool_enum
42
- end
43
- end
44
-
45
-
46
- describe Gecode::Constraints::IntEnum::Channel, ' (two int enums)' do
47
- before do
48
- @model = ChannelSampleProblem.new
49
- @positions = @model.positions
50
- @elements = @model.elements
51
- @invoke_options = lambda do |hash|
52
- @positions.must.channel @elements, hash
53
- @model.solve!
54
- end
55
- @expect_options = option_expectation do |strength, kind, reif_var|
56
- Gecode::Raw.should_receive(:channel).once.with(
57
- an_instance_of(Gecode::Raw::Space),
58
- an_instance_of(Gecode::Raw::IntVarArray),
59
- an_instance_of(Gecode::Raw::IntVarArray), strength, kind)
60
- end
61
- end
62
-
63
- it 'should translate into a channel constraint' do
64
- Gecode::Raw.should_receive(:channel).once.with(
65
- an_instance_of(Gecode::Raw::Space),
66
- anything, anything, Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF)
67
- @invoke_options.call({})
68
- end
69
-
70
- it 'should constrain variables to be channelled' do
71
- @elements.must.channel @positions
72
- @model.solve!
73
- elements = @model.elements.values
74
- positions = @model.elements.values
75
- elements.each_with_index do |element, i|
76
- element.should equal(positions.index(i))
77
- end
78
- end
79
-
80
- it 'should not allow negation' do
81
- lambda{ @elements.must_not.channel @positions }.should raise_error(
82
- Gecode::MissingConstraintError)
83
- end
84
-
85
- it 'should raise error for unsupported right hand sides' do
86
- lambda{ @elements.must.channel 'hello' }.should raise_error(TypeError)
87
- end
88
-
89
- it_should_behave_like 'non-reifiable constraint'
90
- end
91
-
92
- describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as right hand side)' do
93
- before do
94
- @model = ChannelSampleProblem.new
95
- @positions = @model.positions
96
- @sets = @model.sets
97
-
98
- @invoke_options = lambda do |hash|
99
- @positions.must.channel @sets, hash
100
- @model.solve!
101
- end
102
- @expect_options = option_expectation do |strength, kind, reif_var|
103
- Gecode::Raw.should_receive(:channel).once.with(
104
- an_instance_of(Gecode::Raw::Space),
105
- an_instance_of(Gecode::Raw::IntVarArray),
106
- an_instance_of(Gecode::Raw::SetVarArray))
107
- end
108
- end
109
-
110
- it 'should translate into a channel constraint' do
111
- @expect_options.call({})
112
- @positions.must.channel @sets
113
- @model.solve!
114
- end
115
-
116
- it 'should constrain variables to be channelled' do
117
- @positions.must.channel @sets
118
- @model.solve!
119
- sets = @model.sets
120
- positions = @model.positions.values
121
- positions.each_with_index do |position, i|
122
- sets[position].value.should include(i)
123
- end
124
- end
125
-
126
- it_should_behave_like 'non-reifiable set constraint'
127
- end
128
-
129
- describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as left hand side)' do
130
- before do
131
- @model = ChannelSampleProblem.new
132
- @positions = @model.positions
133
- @sets = @model.sets
134
-
135
- @invoke_options = lambda do |hash|
136
- @sets.must.channel @positions, hash
137
- @model.solve!
138
- end
139
- @expect_options = option_expectation do |strength, kind, reif_var|
140
- Gecode::Raw.should_receive(:channel).once.with(
141
- an_instance_of(Gecode::Raw::Space),
142
- an_instance_of(Gecode::Raw::IntVarArray),
143
- an_instance_of(Gecode::Raw::SetVarArray))
144
- end
145
- end
146
-
147
- it 'should translate into a channel constraint' do
148
- @expect_options.call({})
149
- @sets.must.channel @positions
150
- @model.solve!
151
- end
152
-
153
- it 'should not allow negation' do
154
- lambda{ @sets.must_not.channel @positions }.should raise_error(
155
- Gecode::MissingConstraintError)
156
- end
157
-
158
- it 'should raise error for unsupported right hand sides' do
159
- lambda{ @sets.must.channel 'hello' }.should raise_error(TypeError)
160
- end
161
-
162
- it_should_behave_like 'non-reifiable set constraint'
163
- end
164
-
165
- # Requires @model, @bool and @int. Also requires @place_constraint which is a
166
- # method that takes five variables: a boolean variable, an integer variable,
167
- # the name of the equality method to use, whether or not the constraint should
168
- # be negated and a hash of options, and places the channel constraint on them.
169
- describe 'channel constraint between one int and one bool variable', :shared => true do
170
- before do
171
- @invoke_options = lambda do |hash|
172
- @place_constraint.call(@bool, @int, :==, false, hash)
173
- @model.solve!
174
- end
175
- @expect_options = option_expectation do |strength, kind, reif_var|
176
- Gecode::Raw.should_receive(:channel).once.with(
177
- an_instance_of(Gecode::Raw::Space),
178
- an_instance_of(Gecode::Raw::IntVar),
179
- an_instance_of(Gecode::Raw::BoolVar),
180
- strength, kind)
181
- end
182
- end
183
-
184
- ([:==] + Gecode::Constraints::Util::COMPARISON_ALIASES[:==]).each do |ali|
185
- it "should translate #{ali} into a channel constraint" do
186
- @expect_options.call({})
187
- @place_constraint.call(@bool, @int, ali, false, {})
188
- @model.solve!
189
- end
190
- end
191
-
192
- it 'should constrain the int variable to be 1 when the boolean variable is true' do
193
- @bool.must_be.true
194
- @place_constraint.call(@bool, @int, :==, false, {})
195
- @model.solve!
196
- @int.value.should == 1
197
- end
198
-
199
- it 'should constrain the int variable to be 0 when the boolean variable is false' do
200
- @bool.must_be.false
201
- @place_constraint.call(@bool, @int, :==, false, {})
202
- @model.solve!
203
- @int.value.should == 0
204
- end
205
-
206
- it 'should not allow negation' do
207
- lambda do
208
- @place_constraint.call(@bool, @int, :==, true, {})
209
- end.should raise_error(Gecode::MissingConstraintError)
210
- end
211
-
212
- it_should_behave_like 'non-reifiable constraint'
213
- end
214
-
215
- describe Gecode::Constraints::Int::Channel, ' (one int and one bool variable)' do
216
- before do
217
- @model = BoolChannelSampleProblem.new
218
- @bool = @model.bool_var
219
- @int = @model.int_var
220
-
221
- @place_constraint = lambda do |bool, int, equals_method_name, negate, options|
222
- if negate
223
- int.must_not.method(equals_method_name).call(bool, options)
224
- else
225
- int.must.method(equals_method_name).call(bool, options)
226
- end
227
- end
228
- end
229
-
230
- it 'should not shadow linear boolean constraints' do
231
- lambda do
232
- (@bool + @bool).must == @bool
233
- @model.solve!
234
- end.should_not raise_error
235
- end
236
-
237
- it 'should raise error for unsupported right hand sides' do
238
- lambda{ @int.must == 'hello' }.should raise_error(TypeError)
239
- end
240
-
241
- it_should_behave_like 'channel constraint between one int and one bool variable'
242
- end
243
-
244
- describe Gecode::Constraints::Int::Channel, ' (one bool and one int variable)' do
245
- before do
246
- @model = BoolChannelSampleProblem.new
247
- @bool = @model.bool_var
248
- @int = @model.int_var
249
-
250
- @place_constraint = lambda do |bool, int, equals_method_name, negate, options|
251
- if negate
252
- bool.must_not.method(equals_method_name).call(int, options)
253
- else
254
- bool.must.method(equals_method_name).call(int, options)
255
- end
256
- end
257
- end
258
-
259
- it 'should not shadow linear boolean constraints' do
260
- lambda do
261
- @bool.must == @bool + @bool
262
- @model.solve!
263
- end.should_not raise_error
264
- end
265
-
266
- it 'should raise error for unsupported right hand sides' do
267
- lambda{ @bool.must == 'hello' }.should raise_error(TypeError)
268
- end
269
-
270
- it_should_behave_like 'channel constraint between one int and one bool variable'
271
- end
272
-
273
- # Requires @model, @bool_enum and @int. Also requires @place_constraint which
274
- # is a method that takes four variables: a boolean enum, an integer variable,
275
- # whether or not the constraint should be negated and a hash of options, and
276
- # places the channel constraint on them.
277
- describe 'channel constraint between bool enum and int variable', :shared => true do
278
- before do
279
- @invoke_options = lambda do |hash|
280
- @place_constraint.call(@bools, @int, false, hash)
281
- @model.solve!
282
- end
283
- @expect_options = option_expectation do |strength, kind, reif_var|
284
- Gecode::Raw.should_receive(:channel).once.with(
285
- an_instance_of(Gecode::Raw::Space),
286
- an_instance_of(Gecode::Raw::BoolVarArray),
287
- an_instance_of(Gecode::Raw::IntVar), 0,
288
- strength, kind)
289
- end
290
- end
291
-
292
- it 'should channel the bool enum with the integer variable' do
293
- @int.must > 2
294
- @place_constraint.call(@bools, @int, false, {})
295
- @model.solve!.should_not be_nil
296
- int_val = @int.value
297
- @bools.values.each_with_index do |bool, index|
298
- bool.should == (index == int_val)
299
- end
300
- end
301
-
302
- it 'should take the offset into account when channeling' do
303
- @int.must > 2
304
- offset = 1
305
- @place_constraint.call(@bools, @int, false, :offset => offset)
306
- @model.solve!.should_not be_nil
307
- int_val = @int.value
308
- @bools.values.each_with_index do |bool, index|
309
- bool.should == (index + offset == int_val)
310
- end
311
- end
312
-
313
- it 'should not allow negation' do
314
- lambda do
315
- @place_constraint.call(@bools, @int, true, {})
316
- end.should raise_error(Gecode::MissingConstraintError)
317
- end
318
-
319
- it_should_behave_like 'non-reifiable constraint'
320
- end
321
-
322
- describe Gecode::Constraints::BoolEnum::Channel, ' (bool enum as lhs with int variable)' do
323
- before do
324
- @model = BoolChannelSampleProblem.new
325
- @bools = @model.bool_enum
326
- @int = @model.int
327
-
328
- @place_constraint = lambda do |bools, int, negate, options|
329
- unless negate
330
- bools.must.channel(int, options)
331
- else
332
- bools.must_not.channel(int, options)
333
- end
334
- end
335
- end
336
-
337
- it 'should raise error if an integer variable is not given as right hand side' do
338
- lambda do
339
- @bools.must.channel 'hello'
340
- end.should raise_error(TypeError)
341
- end
342
-
343
- it_should_behave_like 'channel constraint between bool enum and int variable'
344
- end
345
-
346
-
347
- describe Gecode::Constraints::BoolEnum::Channel, ' (int variable as lhs with bool enum)' do
348
- before do
349
- @model = BoolChannelSampleProblem.new
350
- @bools = @model.bool_enum
351
- @int = @model.int
352
-
353
- @place_constraint = lambda do |bools, int, negate, options|
354
- unless negate
355
- int.must.channel(bools, options)
356
- else
357
- int.must_not.channel(bools, options)
358
- end
359
- end
360
- end
361
-
362
- it 'should raise error if a boolean enum is not given as right hand side' do
363
- lambda do
364
- @int.must.channel 'hello'
365
- end.should raise_error(TypeError)
366
- end
367
-
368
- it_should_behave_like 'channel constraint between bool enum and int variable'
369
- end
370
-
371
- # Requires @model, @bool_enum and @set. Also requires @place_constraint which
372
- # is a method that takes four variables: a boolean enum, a set variable,
373
- # whether or not the constraint should be negated and a hash of options, and
374
- # places the channel constraint on them.
375
- describe 'channel constraint between set variable and bool enum', :shared => true do
376
- before do
377
- @invoke_options = lambda do |hash|
378
- @place_constraint.call(@bools, @set, false, hash)
379
- @model.solve!
380
- end
381
- @expect_options = option_expectation do |strength, kind, reif_var|
382
- Gecode::Raw.should_receive(:channel).once.with(
383
- an_instance_of(Gecode::Raw::Space),
384
- an_instance_of(Gecode::Raw::BoolVarArray),
385
- an_instance_of(Gecode::Raw::SetVar))
386
- end
387
- end
388
-
389
- it 'should channel the bool enum with the set variable' do
390
- @set.must_be.superset_of [0, 2]
391
- @place_constraint.call(@bools, @set, false, {})
392
- @model.solve!.should_not be_nil
393
- set_values = @set.value
394
- @bools.values.each_with_index do |bool, index|
395
- bool.should == set_values.include?(index)
396
- end
397
- end
398
-
399
- it 'should not allow negation' do
400
- lambda do
401
- @place_constraint.call(@bools, @set, true, {})
402
- end.should raise_error(Gecode::MissingConstraintError)
403
- end
404
-
405
- it_should_behave_like 'non-reifiable set constraint'
406
- end
407
-
408
- describe Gecode::Constraints::Set::Channel, ' (set variable as lhs with bool enum)' do
409
- before do
410
- @model = SetChannelSampleProblem.new
411
- @bools = @model.bool_enum
412
- @set = @model.set
413
-
414
- @place_constraint = lambda do |bools, set, negate, options|
415
- unless negate
416
- set.must.channel(bools, options)
417
- else
418
- set.must_not.channel(bools, options)
419
- end
420
- end
421
- end
422
-
423
- it 'should raise error if a boolean enum is not given as right hand side' do
424
- lambda do
425
- @set.must.channel 'hello'
426
- end.should raise_error(TypeError)
427
- end
428
-
429
- it_should_behave_like 'channel constraint between set variable and bool enum'
430
- end
431
-
432
- describe Gecode::Constraints::Set::Channel, ' (bool enum as lhs with set variable)' do
433
- before do
434
- @model = SetChannelSampleProblem.new
435
- @bools = @model.bool_enum
436
- @set = @model.set
437
-
438
- @place_constraint = lambda do |bools, set, negate, options|
439
- unless negate
440
- bools.must.channel(set, options)
441
- else
442
- bools.must_not.channel(set, options)
443
- end
444
- end
445
- end
446
-
447
- it 'should raise error if an integer variable is not given as right hand side' do
448
- lambda do
449
- @bools.must.channel 'hello'
450
- end.should raise_error(TypeError)
451
- end
452
-
453
- it_should_behave_like 'channel constraint between set variable and bool enum'
454
- end