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
@@ -0,0 +1,101 @@
1
+ require File.dirname(__FILE__) + '/../constraint_helper'
2
+
3
+ class BoolChannelSampleProblem < Gecode::Model
4
+ attr :bool_enum
5
+ attr :bool
6
+ attr :int
7
+
8
+ def initialize
9
+ @bool_enum = bool_var_array(4)
10
+ @int = int_var(0..3)
11
+ @bool = bool_var
12
+
13
+ branch_on @int
14
+ end
15
+ end
16
+
17
+ describe Gecode::Int::Channel, ' (one int and one bool variable)' do
18
+ before do
19
+ @model = BoolChannelSampleProblem.new
20
+ @bool = @model.bool_var
21
+ @int = @model.int_var
22
+
23
+ @types = [:int, :bool]
24
+ @invoke = lambda do |receiver, bool, hash|
25
+ receiver.equal(bool, hash)
26
+ @model.solve!
27
+ end
28
+ @expect = lambda do |var1, var2, opts, reif_var|
29
+ Gecode::Raw.should_receive(:channel).once.with(
30
+ an_instance_of(Gecode::Raw::Space),
31
+ var1, var2, *opts)
32
+ end
33
+ end
34
+
35
+ it 'should not shadow linear boolean constraints' do
36
+ lambda do
37
+ (@bool + @bool).must == @bool
38
+ @model.solve!
39
+ end.should_not raise_error
40
+ end
41
+
42
+ it 'should constrain the int variable to be 1 when the boolean variable is true' do
43
+ @bool.must_be.true
44
+ @int.must == @bool
45
+ @model.solve!
46
+ @int.value.should == 1
47
+ end
48
+
49
+ it 'should constrain the int variable to be 0 when the boolean variable is false' do
50
+ @bool.must_be.false
51
+ @int.must == @bool
52
+ @model.solve!
53
+ @int.value.should == 0
54
+ end
55
+
56
+ it_should_behave_like 'non-reifiable constraint'
57
+ it_should_behave_like 'non-negatable constraint'
58
+ end
59
+
60
+ describe Gecode::Int::Channel, ' (one bool and one int variable)' do
61
+ before do
62
+ @model = BoolChannelSampleProblem.new
63
+ @bool = @model.bool_var
64
+ @int = @model.int_var
65
+
66
+ @types = [:bool, :int]
67
+ @invoke = lambda do |receiver, int, hash|
68
+ receiver.equal(int, hash)
69
+ @model.solve!
70
+ end
71
+ @expect = lambda do |var1, var2, opts, reif_var|
72
+ Gecode::Raw.should_receive(:channel).once.with(
73
+ an_instance_of(Gecode::Raw::Space),
74
+ var2, var1, *opts)
75
+ end
76
+ end
77
+
78
+ it 'should not shadow linear boolean constraints' do
79
+ lambda do
80
+ @bool.must == @bool + @bool
81
+ @model.solve!
82
+ end.should_not raise_error
83
+ end
84
+
85
+ it 'should constrain the int variable to be 1 when the boolean variable is true' do
86
+ @bool.must_be.true
87
+ @bool.must == @int
88
+ @model.solve!
89
+ @int.value.should == 1
90
+ end
91
+
92
+ it 'should constrain the int variable to be 0 when the boolean variable is false' do
93
+ @bool.must_be.false
94
+ @bool.must == @int
95
+ @model.solve!
96
+ @int.value.should == 0
97
+ end
98
+
99
+ it_should_behave_like 'non-reifiable constraint'
100
+ it_should_behave_like 'non-negatable constraint'
101
+ end
@@ -0,0 +1,106 @@
1
+ require File.dirname(__FILE__) + '/../constraint_helper'
2
+
3
+ describe Gecode::Int::Domain, ' (non-range)' do
4
+ before do
5
+ @model = Gecode::Model.new
6
+ @domain = 0..3
7
+ @x = @model.int_var(@domain)
8
+ @non_range_domain = [1, 3]
9
+
10
+ @types = [:int]
11
+ @invoke = lambda do |receiver, hash|
12
+ receiver.in(@non_range_domain, hash)
13
+ @model.solve!
14
+ end
15
+ @expect = lambda do |var, opts, reif_var|
16
+ if reif_var.nil?
17
+ Gecode::Raw.should_receive(:dom).once.with(
18
+ an_instance_of(Gecode::Raw::Space),
19
+ var, an_instance_of(Gecode::Raw::IntSet),
20
+ *opts)
21
+ else
22
+ Gecode::Raw.should_receive(:dom).once.with(
23
+ an_instance_of(Gecode::Raw::Space),
24
+ var, an_instance_of(Gecode::Raw::IntSet),
25
+ reif_var, *opts)
26
+ end
27
+ end
28
+ end
29
+
30
+ it 'should constrain the domain of the variable' do
31
+ @x.must_be.in @non_range_domain
32
+ @model.solve!
33
+
34
+ @x.should have_domain(@non_range_domain)
35
+ end
36
+
37
+ it 'should handle negation' do
38
+ @x.must_not_be.in @non_range_domain
39
+ @model.solve!
40
+
41
+ @x.should have_domain(@domain.to_a - @non_range_domain.to_a)
42
+ end
43
+
44
+ it_should_behave_like 'reifiable constraint'
45
+ end
46
+
47
+ describe Gecode::Int::Domain, ' (range)' do
48
+ before do
49
+ @model = Gecode::Model.new
50
+ @domain = 0..3
51
+ @operand = @x = @model.int_var(@domain)
52
+ @range_domain = 1..2
53
+ @three_dot_range_domain = 1...2
54
+
55
+ @types = [:int]
56
+ @invoke = lambda do |receiver, hash|
57
+ receiver.in(@range_domain, hash)
58
+ @model.solve!
59
+ end
60
+ @expect = lambda do |var, opts, reif_var|
61
+ @model.allow_space_access do
62
+ if reif_var.nil?
63
+ Gecode::Raw.should_receive(:dom).once.with(
64
+ an_instance_of(Gecode::Raw::Space),
65
+ var, @range_domain.first, @range_domain.last,
66
+ *opts)
67
+ else
68
+ Gecode::Raw.should_receive(:dom).once.with(
69
+ an_instance_of(Gecode::Raw::Space),
70
+ var, @range_domain.first, @range_domain.last,
71
+ reif_var, *opts)
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ it 'should constrain the domain of the variable' do
78
+ @x.must_be.in @range_domain
79
+ @model.solve!
80
+
81
+ @x.should have_domain(@range_domain)
82
+ end
83
+
84
+ it 'should handle negation' do
85
+ @x.must_not_be.in @range_domain
86
+ @model.solve!
87
+
88
+ @x.should have_domain(@domain.to_a - @range_domain.to_a)
89
+ end
90
+
91
+ it 'should treat three dot ranges correctly' do
92
+ @x.must_be.in @three_dot_range_domain
93
+ @model.solve!
94
+
95
+ @x.should have_domain(@three_dot_range_domain)
96
+ end
97
+
98
+ it 'should handle three dot range with negation' do
99
+ @x.must_not_be.in @three_dot_range_domain
100
+ @model.solve!
101
+
102
+ @x.should have_domain(@domain.to_a - @three_dot_range_domain.to_a)
103
+ end
104
+
105
+ it_should_behave_like 'reifiable constraint'
106
+ end
@@ -0,0 +1,183 @@
1
+ require File.dirname(__FILE__) + '/../constraint_helper'
2
+
3
+ # This is neither an operand or a constraint spec. It is mostly a sanity
4
+ # check.
5
+
6
+ class LinearSampleProblem < Gecode::Model
7
+ attr :x
8
+ attr :y
9
+ attr :z
10
+
11
+ def initialize(x_dom, y_dom, z_dom)
12
+ @x = self.int_var(x_dom)
13
+ @y = self.int_var(y_dom)
14
+ @z = self.int_var(z_dom)
15
+ branch_on wrap_enum([@x, @y, @z])
16
+ end
17
+ end
18
+
19
+ describe Gecode::Int::Linear do
20
+ before do
21
+ @x_dom = 0..2
22
+ @y_dom = -3..3
23
+ @z_dom = 0..10
24
+ @model = LinearSampleProblem.new(@x_dom, @y_dom, @z_dom)
25
+ @x = @model.x
26
+ @y = @model.y
27
+ @z = @model.z
28
+ @operand = @x + @y
29
+ end
30
+
31
+ it 'should handle addition with a variable' do
32
+ (@x + @y).must == 0
33
+ sol = @model.solve!
34
+ x = sol.x.value
35
+ y = sol.y.value
36
+ (x + y).should be_zero
37
+ end
38
+
39
+ it 'should handle reification (1)' do
40
+ bool = @model.bool_var
41
+ (@x + @y).must.equal(0, :reify => bool)
42
+ bool.must_be.false
43
+ sol = @model.solve!
44
+ x = sol.x.value
45
+ y = sol.y.value
46
+ (x + y).should_not be_zero
47
+ end
48
+
49
+ it 'should handle reification (2)' do
50
+ bool = @model.bool_var
51
+ (@x + @y).must.equal(0, :reify => bool)
52
+ bool.must_be.true
53
+ sol = @model.solve!
54
+ x = sol.x.value
55
+ y = sol.y.value
56
+ (x + y).should be_zero
57
+ end
58
+
59
+ it 'should handle addition with multiple variables' do
60
+ (@x + @y + @z).must == 0
61
+ sol = @model.solve!
62
+ x = sol.x.value
63
+ y = sol.y.value
64
+ z = sol.z.value
65
+ (x + y + z).should be_zero
66
+ end
67
+
68
+ it 'should handle subtraction with a variable' do
69
+ (@x - @y).must == 0
70
+ sol = @model.solve!
71
+ x = sol.x.value
72
+ y = sol.y.value
73
+ (x - y).should be_zero
74
+ end
75
+
76
+ it 'should handle non-zero constants as right hand side' do
77
+ (@x + @y).must == 1
78
+ sol = @model.solve!
79
+ x = sol.x.value
80
+ y = sol.y.value
81
+ (x + y).should equal(1)
82
+ end
83
+
84
+ it 'should handle variables as right hand side' do
85
+ (@x + @y).must == @z
86
+ sol = @model.solve!
87
+ x = sol.x.value
88
+ y = sol.y.value
89
+ z = sol.z.value
90
+ (x + y).should equal(z)
91
+ end
92
+
93
+ it 'should handle linear expressions as right hand side' do
94
+ (@x + @y).must == @z + @y
95
+ sol = @model.solve!
96
+ x = sol.x.value
97
+ y = sol.y.value
98
+ z = sol.z.value
99
+ (x + y).should equal(z + y)
100
+ end
101
+
102
+ it 'should handle linear expressions as right hand side with variable as left hand side' do
103
+ @x.must == @z + @y
104
+ sol = @model.solve!
105
+ x = sol.x.value
106
+ y = sol.y.value
107
+ z = sol.z.value
108
+ x.should equal(z + y)
109
+ end
110
+
111
+ it 'should raise error on invalid right hand sides' do
112
+ lambda{ ((@x + @y).must == 'z') }.should raise_error(TypeError)
113
+ end
114
+
115
+ it 'should handle coefficients other than 1' do
116
+ (@x * 2 + @y).must == 0
117
+ sol = @model.solve!
118
+ x = sol.x.value
119
+ y = sol.y.value
120
+ (2*x + y).should equal(0)
121
+ end
122
+
123
+ it 'should handle addition with constants' do
124
+ (@y + 2).must == 1
125
+ sol = @model.solve!
126
+ y = sol.y.value
127
+ (y + 2).should equal(1)
128
+ end
129
+
130
+ it 'should handle subtraction with a constant' do
131
+ (@x - 2).must == 0
132
+ sol = @model.solve!
133
+ x = sol.x.value
134
+ (x - 2).should be_zero
135
+ end
136
+
137
+ it 'should a single variable as left hande side' do
138
+ @x.must == @y + @z
139
+ sol = @model.solve!
140
+ x = sol.x.value
141
+ y = sol.y.value
142
+ z = sol.z.value
143
+ x.should equal(y + z)
144
+ end
145
+
146
+ it 'should handle parenthesis' do
147
+ (@x - (@y + @z)).must == 1
148
+ sol = @model.solve!
149
+ x = sol.x.value
150
+ y = sol.y.value
151
+ z = sol.z.value
152
+ (x - (y + z)).should equal(1)
153
+ end
154
+
155
+ it 'should handle multiplication of parenthesis' do
156
+ (((@x + @y*10)*10 + @z)*10).must == 0
157
+ sol = @model.solve!
158
+ x = sol.x.value
159
+ y = sol.y.value
160
+ z = sol.z.value
161
+ (((x + y*10)*10 + z)*10).should equal(0)
162
+ end
163
+
164
+ relations = ['>', '>=', '<', '<=', '==']
165
+
166
+ relations.each do |relation|
167
+ it "should handle #{relation} with constant integers" do
168
+ (@x + @y).must.send(relation, 1)
169
+ sol = @model.solve!
170
+ sol.should_not be_nil
171
+ (sol.x.value + sol.y.value).should.send(relation, 1)
172
+ end
173
+ end
174
+
175
+ relations.each do |relation|
176
+ it "should handle negated #{relation} with constant integers" do
177
+ (@x + @y).must_not.send(relation, 1)
178
+ sol = @model.solve!
179
+ sol.should_not be_nil
180
+ (sol.x.value + sol.y.value).should_not.send(relation, 1)
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,97 @@
1
+ require File.dirname(__FILE__) + '/../property_helper'
2
+
3
+ class LinearPropertySampleProblem < Gecode::Model
4
+ attr :x
5
+ attr :y
6
+ attr :z
7
+
8
+ def initialize
9
+ @x = self.int_var(0..2)
10
+ @y = self.int_var(-3..3)
11
+ @z = self.int_var(0..10)
12
+ branch_on wrap_enum([@x, @y, @z])
13
+ end
14
+ end
15
+
16
+ describe Gecode::Int::Linear, ' (+ property)' do
17
+ before do
18
+ @model = LinearPropertySampleProblem.new
19
+ @x = @model.x
20
+ @y = @model.y
21
+ @z = @model.z
22
+
23
+ # For int operand producing property spec.
24
+ @property_types = [:int, :int]
25
+ @select_property = lambda do |int1, int2|
26
+ int1 + int2
27
+ end
28
+ @selected_property = @x + @y
29
+ @constraint_class =
30
+ Gecode::Int::Linear::LinearRelationConstraint
31
+ end
32
+
33
+ it 'should constrain the sum' do
34
+ (@x + @y).must == 5
35
+ @model.solve!
36
+ (@x.value + @y.value).should == 5
37
+ end
38
+
39
+ it_should_behave_like(
40
+ 'property that produces int operand by short circuiting relations')
41
+ end
42
+
43
+ describe Gecode::Int::Linear, ' (- property)' do
44
+ before do
45
+ @model = LinearPropertySampleProblem.new
46
+ @x = @model.x
47
+ @y = @model.y
48
+ @z = @model.z
49
+
50
+ # For int operand producing property spec.
51
+ @property_types = [:int, :int]
52
+ @select_property = lambda do |int1, int2|
53
+ int1 - int2
54
+ end
55
+ @selected_property = @x - @y
56
+ @constraint_class =
57
+ Gecode::Int::Linear::LinearRelationConstraint
58
+ end
59
+
60
+ it 'should constrain the difference' do
61
+ (@x - @y).must == 1
62
+ @model.solve!
63
+ (@x.value - @y.value).should == 1
64
+ end
65
+
66
+ it_should_behave_like(
67
+ 'property that produces int operand by short circuiting relations')
68
+ end
69
+
70
+ describe Gecode::Int::Linear, ' (* property)' do
71
+ before do
72
+ @model = LinearPropertySampleProblem.new
73
+ @x = @model.x
74
+ @y = @model.y
75
+ @z = @model.z
76
+
77
+ # For int operand producing property spec.
78
+ @property_types = [:int]
79
+ @select_property = lambda do |int|
80
+ int * 17
81
+ end
82
+ @selected_property = @x * 2
83
+ @constraint_class =
84
+ Gecode::Int::Linear::LinearRelationConstraint
85
+ end
86
+
87
+ it 'should constrain the value times a constant' do
88
+ (@x * 2).must == 4
89
+ @model.solve!
90
+ (@x.value * 2).should == 4
91
+ end
92
+
93
+ it_should_behave_like(
94
+ 'property that produces int operand by short circuiting relations')
95
+ end
96
+
97
+