gecoder 0.8.3 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +15 -0
- data/README +6 -2
- data/example/equation_system.rb +15 -0
- data/example/magic_sequence.rb +7 -7
- data/example/money.rb +36 -0
- data/example/queens.rb +7 -8
- data/example/send_most_money.rb +1 -1
- data/example/square_tiling.rb +2 -2
- data/example/sudoku-set.rb +11 -12
- data/example/sudoku.rb +40 -45
- data/ext/extconf.rb +0 -0
- data/lib/gecoder/bindings.rb +42 -0
- data/lib/gecoder/bindings/bindings.rb +16 -0
- data/lib/gecoder/interface.rb +2 -1
- data/lib/gecoder/interface/branch.rb +16 -9
- data/lib/gecoder/interface/constraints.rb +410 -451
- data/lib/gecoder/interface/constraints/bool/boolean.rb +205 -213
- data/lib/gecoder/interface/constraints/bool/channel.rb +4 -5
- data/lib/gecoder/interface/constraints/bool/linear.rb +192 -21
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +43 -39
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +43 -49
- data/lib/gecoder/interface/constraints/bool_enum/relation.rb +38 -71
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +73 -22
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +140 -61
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +4 -4
- data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
- data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +131 -130
- data/lib/gecoder/interface/constraints/int/channel.rb +21 -31
- data/lib/gecoder/interface/constraints/int/domain.rb +45 -42
- data/lib/gecoder/interface/constraints/int/linear.rb +85 -239
- data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +55 -64
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +35 -37
- data/lib/gecoder/interface/constraints/int_enum/count.rb +53 -78
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +36 -46
- data/lib/gecoder/interface/constraints/int_enum/element.rb +39 -57
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +15 -19
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +65 -72
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +42 -45
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +79 -22
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +215 -44
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +14 -14
- data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
- data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +43 -53
- data/lib/gecoder/interface/constraints/set/channel.rb +26 -29
- data/lib/gecoder/interface/constraints/set/connection.rb +89 -152
- data/lib/gecoder/interface/constraints/set/domain.rb +112 -65
- data/lib/gecoder/interface/constraints/set/include.rb +36 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +96 -110
- data/lib/gecoder/interface/constraints/set/relation.rb +114 -137
- data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
- data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +23 -27
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +18 -19
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +62 -53
- data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +73 -23
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +222 -57
- data/lib/gecoder/interface/enum_matrix.rb +4 -4
- data/lib/gecoder/interface/enum_wrapper.rb +71 -22
- data/lib/gecoder/interface/model.rb +167 -12
- data/lib/gecoder/interface/model_sugar.rb +84 -0
- data/lib/gecoder/interface/search.rb +30 -18
- data/lib/gecoder/interface/variables.rb +103 -33
- data/lib/gecoder/version.rb +2 -2
- data/specs/bool_var.rb +19 -12
- data/specs/constraints/{boolean.rb → bool/boolean.rb} +103 -28
- data/specs/constraints/bool/boolean_properties.rb +51 -0
- data/specs/constraints/bool/linear.rb +213 -0
- data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
- data/specs/constraints/bool_enum/channel.rb +102 -0
- data/specs/constraints/{extensional.rb → bool_enum/extensional.rb} +32 -101
- data/specs/constraints/constraint_helper.rb +149 -179
- data/specs/constraints/constraint_receivers.rb +103 -0
- data/specs/constraints/constraints.rb +6 -63
- data/specs/constraints/fixnum_enum/element.rb +58 -0
- data/specs/constraints/fixnum_enum/operation.rb +67 -0
- data/specs/constraints/int/arithmetic.rb +149 -0
- data/specs/constraints/int/channel.rb +101 -0
- data/specs/constraints/int/domain.rb +106 -0
- data/specs/constraints/int/linear.rb +183 -0
- data/specs/constraints/int/linear_properties.rb +97 -0
- data/specs/constraints/int/relation.rb +84 -0
- data/specs/constraints/int_enum/arithmetic.rb +72 -0
- data/specs/constraints/int_enum/channel.rb +57 -0
- data/specs/constraints/int_enum/count.rb +72 -0
- data/specs/constraints/int_enum/distinct.rb +80 -0
- data/specs/constraints/int_enum/element.rb +61 -0
- data/specs/constraints/int_enum/equality.rb +29 -0
- data/specs/constraints/int_enum/extensional.rb +224 -0
- data/specs/constraints/int_enum/sort.rb +167 -0
- data/specs/constraints/operands.rb +264 -0
- data/specs/constraints/property_helper.rb +443 -0
- data/specs/constraints/reification_sugar.rb +4 -5
- data/specs/constraints/selected_set/select.rb +56 -0
- data/specs/constraints/selected_set/select_properties.rb +157 -0
- data/specs/constraints/set/cardinality.rb +58 -0
- data/specs/constraints/set/cardinality_properties.rb +46 -0
- data/specs/constraints/set/channel.rb +77 -0
- data/specs/constraints/set/connection.rb +176 -0
- data/specs/constraints/set/domain.rb +197 -0
- data/specs/constraints/set/include.rb +36 -0
- data/specs/constraints/set/operation.rb +132 -0
- data/specs/constraints/set/relation.rb +117 -0
- data/specs/constraints/set_elements/relation.rb +84 -0
- data/specs/constraints/set_enum/channel.rb +80 -0
- data/specs/constraints/set_enum/distinct.rb +59 -0
- data/specs/constraints/set_enum/operation.rb +111 -0
- data/specs/constraints/set_enum/select.rb +73 -0
- data/specs/enum_wrapper.rb +53 -3
- data/specs/int_var.rb +44 -25
- data/specs/model.rb +58 -1
- data/specs/model_sugar.rb +30 -0
- data/specs/search.rb +24 -5
- data/specs/selected_set.rb +39 -0
- data/specs/set_elements.rb +34 -0
- data/specs/set_var.rb +22 -8
- data/specs/spec_helper.rb +206 -6
- data/tasks/distribution.rake +22 -7
- data/tasks/svn.rake +3 -1
- metadata +218 -134
- data/lib/gecoder/interface/constraints/set_enum/selection.rb +0 -217
- data/specs/constraints/arithmetic.rb +0 -351
- data/specs/constraints/bool_enum_relation.rb +0 -160
- data/specs/constraints/cardinality.rb +0 -157
- data/specs/constraints/channel.rb +0 -454
- data/specs/constraints/connection.rb +0 -369
- data/specs/constraints/count.rb +0 -146
- data/specs/constraints/distinct.rb +0 -164
- data/specs/constraints/element.rb +0 -108
- data/specs/constraints/equality.rb +0 -31
- data/specs/constraints/int_domain.rb +0 -70
- data/specs/constraints/int_relation.rb +0 -82
- data/specs/constraints/linear.rb +0 -340
- data/specs/constraints/selection.rb +0 -292
- data/specs/constraints/set_domain.rb +0 -185
- data/specs/constraints/set_operation.rb +0 -285
- data/specs/constraints/set_relation.rb +0 -197
- data/specs/constraints/sort.rb +0 -179
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
Gecode::Util::RELATION_TYPES.each_pair do |relation, rel_value|
|
4
|
+
describe Gecode::Int::Relation, " (#{relation} with int op)" do
|
5
|
+
before do
|
6
|
+
@model = Gecode::Model.new
|
7
|
+
|
8
|
+
# For constraint spec.
|
9
|
+
@types = [:int, :int]
|
10
|
+
@invoke = lambda do |receiver, op, hash|
|
11
|
+
receiver.method(relation).call(op, hash)
|
12
|
+
@model.solve!
|
13
|
+
end
|
14
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
15
|
+
if reif_var.nil?
|
16
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
17
|
+
an_instance_of(Gecode::Raw::Space),
|
18
|
+
var1, rel_value, var2, *opts)
|
19
|
+
else
|
20
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
21
|
+
an_instance_of(Gecode::Raw::Space),
|
22
|
+
var1, rel_value, var2, reif_var, *opts)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should constrain the #{relation} with an int operand" do
|
28
|
+
ints = @model.int_var_array(2, -5..5)
|
29
|
+
@model.branch_on ints
|
30
|
+
int1, int2 = ints
|
31
|
+
int1.must.method(relation).call(int2)
|
32
|
+
@model.solve!
|
33
|
+
int1.value.should.method(relation).call(int2.value)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should constrain the negated #{relation} with an int operand" do
|
37
|
+
ints = @model.int_var_array(2, -5..5)
|
38
|
+
@model.branch_on ints
|
39
|
+
int1, int2 = ints
|
40
|
+
int1.must_not.method(relation).call(int2)
|
41
|
+
@model.solve!
|
42
|
+
int1.value.should_not.method(relation).call(int2.value)
|
43
|
+
end
|
44
|
+
|
45
|
+
it_should_behave_like 'reifiable constraint'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Gecode::Util::RELATION_TYPES.each_pair do |relation, rel_value|
|
50
|
+
describe Gecode::Int::Relation, " (#{relation} with fixnum)" do
|
51
|
+
before do
|
52
|
+
@model = Gecode::Model.new
|
53
|
+
|
54
|
+
# For constraint spec.
|
55
|
+
@types = [:int]
|
56
|
+
@invoke = lambda do |receiver, hash|
|
57
|
+
receiver.method(relation).call(17, hash)
|
58
|
+
@model.solve!
|
59
|
+
end
|
60
|
+
@expect = lambda do |var, opts, reif_var|
|
61
|
+
if reif_var.nil?
|
62
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
63
|
+
an_instance_of(Gecode::Raw::Space),
|
64
|
+
var, rel_value, 17, *opts)
|
65
|
+
else
|
66
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
67
|
+
an_instance_of(Gecode::Raw::Space),
|
68
|
+
var, rel_value, 17, reif_var, *opts)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should constrain the #{relation} with a fixnum" do
|
74
|
+
int = @model.int_var(-5..5)
|
75
|
+
@model.branch_on int
|
76
|
+
int.must.method(relation).call(3)
|
77
|
+
@model.solve!
|
78
|
+
int.value.should.method(relation).call(3)
|
79
|
+
end
|
80
|
+
|
81
|
+
it_should_behave_like 'reifiable constraint'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../property_helper'
|
2
|
+
|
3
|
+
class IntEnumArithmeticSampleProblem < Gecode::Model
|
4
|
+
attr :numbers
|
5
|
+
attr :var
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@numbers = int_var_array(4, 0..9)
|
9
|
+
@var = int_var(-9..9)
|
10
|
+
branch_on @numbers
|
11
|
+
branch_on @var
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe Gecode::IntEnum::Arithmetic, ' (max)' do
|
16
|
+
before do
|
17
|
+
@model = IntEnumArithmeticSampleProblem.new
|
18
|
+
@numbers = @model.numbers
|
19
|
+
@var = @model.var
|
20
|
+
|
21
|
+
@property_types = [:int_enum]
|
22
|
+
@select_property = lambda do |int_enum|
|
23
|
+
int_enum.max
|
24
|
+
end
|
25
|
+
@selected_property = @numbers.max
|
26
|
+
@constraint_class = Gecode::BlockConstraint
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should constrain the maximum value' do
|
30
|
+
@numbers.max.must > 5
|
31
|
+
@model.solve!.numbers.values.max.should > 5
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should translate into a max constraint' do
|
35
|
+
Gecode::Raw.should_receive(:max)
|
36
|
+
@numbers.max.must == 5
|
37
|
+
@model.solve!
|
38
|
+
end
|
39
|
+
|
40
|
+
it_should_behave_like(
|
41
|
+
'property that produces int operand by short circuiting equality')
|
42
|
+
end
|
43
|
+
|
44
|
+
describe Gecode::IntEnum::Arithmetic, ' (min)' do
|
45
|
+
before do
|
46
|
+
@model = IntEnumArithmeticSampleProblem.new
|
47
|
+
@numbers = @model.numbers
|
48
|
+
@var = @model.var
|
49
|
+
|
50
|
+
@property_types = [:int_enum]
|
51
|
+
@select_property = lambda do |int_enum|
|
52
|
+
int_enum.min
|
53
|
+
end
|
54
|
+
@selected_property = @numbers.min
|
55
|
+
@constraint_class = Gecode::BlockConstraint
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should constrain the minimum value' do
|
59
|
+
@numbers.min.must > 5
|
60
|
+
@model.solve!.numbers.values.min.should > 5
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should translate into a min constraint' do
|
64
|
+
Gecode::Raw.should_receive(:min)
|
65
|
+
@numbers.min.must == 5
|
66
|
+
@model.solve!
|
67
|
+
end
|
68
|
+
|
69
|
+
it_should_behave_like(
|
70
|
+
'property that produces int operand by short circuiting equality')
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
class ChannelSampleProblem < Gecode::Model
|
4
|
+
attr :elements
|
5
|
+
attr :positions
|
6
|
+
attr :sets
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@elements = int_var_array(4, 0..3)
|
10
|
+
@elements.must_be.distinct
|
11
|
+
@positions = int_var_array(4, 0..3)
|
12
|
+
@positions.must_be.distinct
|
13
|
+
@sets = set_var_array(4, [], 0..3)
|
14
|
+
branch_on @positions
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe Gecode::IntEnum::Channel, ' (two int enums)' do
|
19
|
+
before do
|
20
|
+
@model = ChannelSampleProblem.new
|
21
|
+
@positions = @model.positions
|
22
|
+
@elements = @model.elements
|
23
|
+
|
24
|
+
@types = [:int_enum, :int_enum]
|
25
|
+
@invoke = lambda do |receiver, int_enum, hash|
|
26
|
+
receiver.channel(int_enum, hash)
|
27
|
+
@model.solve!
|
28
|
+
end
|
29
|
+
@expect = lambda do |var1, var2, opts, reif_var|
|
30
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
31
|
+
an_instance_of(Gecode::Raw::Space),
|
32
|
+
var1, var2, *opts)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should translate into a channel constraint' do
|
37
|
+
Gecode::Raw.should_receive(:channel).once.with(
|
38
|
+
an_instance_of(Gecode::Raw::Space),
|
39
|
+
anything, anything, Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF)
|
40
|
+
@positions.must.channel @elements
|
41
|
+
@model.solve!
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should constrain variables to be channelled' do
|
45
|
+
@elements.must.channel @positions
|
46
|
+
@model.solve!
|
47
|
+
elements = @model.elements.values
|
48
|
+
positions = @model.elements.values
|
49
|
+
elements.each_with_index do |element, i|
|
50
|
+
element.should equal(positions.index(i))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it_should_behave_like 'non-reifiable constraint'
|
55
|
+
it_should_behave_like 'non-negatable constraint'
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../property_helper'
|
2
|
+
|
3
|
+
class CountSampleProblem < Gecode::Model
|
4
|
+
attr :list
|
5
|
+
attr :element
|
6
|
+
attr :target
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@list = int_var_array(4, 0..3)
|
10
|
+
@element = int_var(0..3)
|
11
|
+
@target = int_var(0..4)
|
12
|
+
branch_on @list
|
13
|
+
branch_on @element
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Gecode::IntEnum::Count, ' (with int var)' do
|
18
|
+
before do
|
19
|
+
@model = CountSampleProblem.new
|
20
|
+
@list = @model.list
|
21
|
+
@element = @model.element
|
22
|
+
@target = @model.target
|
23
|
+
|
24
|
+
# For int operand producing property spec.
|
25
|
+
@property_types = [:int_enum, :int]
|
26
|
+
@select_property = lambda do |int_enum, int|
|
27
|
+
int_enum.count(int)
|
28
|
+
end
|
29
|
+
@selected_property = @list.count(@element)
|
30
|
+
@constraint_class =
|
31
|
+
Gecode::IntEnum::Count::CountConstraint
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should constrain the count' do
|
35
|
+
@list.count(@element).must == 2
|
36
|
+
@model.solve!
|
37
|
+
@list.values.map{ |x| x == @element.value }.inject(0) do |sum, b|
|
38
|
+
sum += b ? 1 : 0
|
39
|
+
end.should == 2
|
40
|
+
end
|
41
|
+
|
42
|
+
it_should_behave_like(
|
43
|
+
'property that produces int operand by short circuiting relations')
|
44
|
+
end
|
45
|
+
|
46
|
+
describe Gecode::IntEnum::Count, ' (with fixnum)' do
|
47
|
+
before do
|
48
|
+
@model = CountSampleProblem.new
|
49
|
+
@list = @model.list
|
50
|
+
@target = @model.target
|
51
|
+
|
52
|
+
# For int operand producing property spec.
|
53
|
+
@property_types = [:int_enum]
|
54
|
+
@select_property = lambda do |int_enum|
|
55
|
+
int_enum.count(1)
|
56
|
+
end
|
57
|
+
@selected_property = @list.count(1)
|
58
|
+
@constraint_class =
|
59
|
+
Gecode::IntEnum::Count::CountConstraint
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should constrain the count' do
|
63
|
+
@list.count(1).must == 2
|
64
|
+
@model.solve!
|
65
|
+
@list.values.map{ |x| x == 1 }.inject(0) do |sum, b|
|
66
|
+
sum += b ? 1 : 0
|
67
|
+
end.should == 2
|
68
|
+
end
|
69
|
+
|
70
|
+
it_should_behave_like(
|
71
|
+
'property that produces int operand by short circuiting relations')
|
72
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
class DistinctSampleProblem < Gecode::Model
|
4
|
+
def initialize
|
5
|
+
vars_is_an int_var_array(2, 0..1)
|
6
|
+
branch_on vars
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Gecode::IntEnum::Distinct do
|
11
|
+
before do
|
12
|
+
@model = DistinctSampleProblem.new
|
13
|
+
|
14
|
+
@types = [:int_enum]
|
15
|
+
@invoke = lambda do |receiver, hash|
|
16
|
+
receiver.distinct(hash)
|
17
|
+
@model.solve!
|
18
|
+
end
|
19
|
+
@expect = lambda do |var, opts, reif_var|
|
20
|
+
Gecode::Raw.should_receive(:distinct).once.with(
|
21
|
+
an_instance_of(Gecode::Raw::Space),
|
22
|
+
var, *opts)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should constrain variables to be distinct' do
|
27
|
+
@model.vars.must_be.distinct
|
28
|
+
@model.solve!
|
29
|
+
@model.vars[0].value.should_not == @model.vars[1].value
|
30
|
+
end
|
31
|
+
|
32
|
+
it_should_behave_like 'non-reifiable constraint'
|
33
|
+
it_should_behave_like 'non-negatable constraint'
|
34
|
+
end
|
35
|
+
|
36
|
+
describe Gecode::IntEnum::Distinct, ' (with offsets)' do
|
37
|
+
before do
|
38
|
+
@model = DistinctSampleProblem.new
|
39
|
+
|
40
|
+
@types = [:int_enum]
|
41
|
+
@invoke = lambda do |receiver, hash|
|
42
|
+
receiver.distinct hash.update(:offsets => [1,2])
|
43
|
+
@model.solve!
|
44
|
+
end
|
45
|
+
@expect = lambda do |var, opts, reif_var|
|
46
|
+
if reif_var.nil?
|
47
|
+
Gecode::Raw.should_receive(:distinct).once.with(
|
48
|
+
an_instance_of(Gecode::Raw::Space),
|
49
|
+
[1,2], var, *opts)
|
50
|
+
else
|
51
|
+
Gecode::Raw.should_receive(:distinct).once.with(
|
52
|
+
an_instance_of(Gecode::Raw::Space),
|
53
|
+
[1,2], var, reif_var, *opts)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should constrain variables to be distinct' do
|
59
|
+
@model.vars.must_be.distinct(:offsets => [-1, 0])
|
60
|
+
x, y = @model.solve!.vars
|
61
|
+
(x.value - 1).should_not == y.value
|
62
|
+
end
|
63
|
+
|
64
|
+
# This tests two distinct in conjunction. It's here because of a bug found.
|
65
|
+
it 'should play nice with normal distinct' do
|
66
|
+
@model.vars.must_be.distinct(:offsets => [-1, 0])
|
67
|
+
@model.vars.must_be.distinct(:offsets => [0, -1])
|
68
|
+
@model.vars.must_be.distinct
|
69
|
+
lambda{ @model.solve! }.should raise_error(Gecode::NoSolutionError)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should raise error if the offsets are of an incorrect type' do
|
73
|
+
lambda do
|
74
|
+
@model.vars.must_be.distinct(:offsets => :foo)
|
75
|
+
end.should raise_error(TypeError)
|
76
|
+
end
|
77
|
+
|
78
|
+
it_should_behave_like 'non-reifiable constraint'
|
79
|
+
it_should_behave_like 'non-negatable constraint'
|
80
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../property_helper'
|
2
|
+
|
3
|
+
class ElementSampleProblem < Gecode::Model
|
4
|
+
attr :prices
|
5
|
+
attr :store
|
6
|
+
attr :price
|
7
|
+
attr :fixnum_prices
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
prices = [17, 63, 45, 63]
|
11
|
+
@fixnum_prices = wrap_enum(prices)
|
12
|
+
@prices = int_var_array(4, prices)
|
13
|
+
@store = int_var(0...prices.size)
|
14
|
+
@price = int_var(prices)
|
15
|
+
branch_on @store
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe Gecode::IntEnum::Element do
|
20
|
+
before do
|
21
|
+
@model = ElementSampleProblem.new
|
22
|
+
@prices = @model.prices
|
23
|
+
@target = @price = @model.price
|
24
|
+
@store = @model.store
|
25
|
+
|
26
|
+
# For int operand producing property spec.
|
27
|
+
@property_types = [:int_enum, :int]
|
28
|
+
@select_property = lambda do |int_enum, int|
|
29
|
+
int_enum[int]
|
30
|
+
end
|
31
|
+
@selected_property = @prices[@store]
|
32
|
+
@constraint_class = Gecode::BlockConstraint
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should not disturb normal array access' do
|
36
|
+
@prices[2].should_not be_nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should constrain the selected element' do
|
40
|
+
@prices[@store].must == 63
|
41
|
+
@prices.values_at(0,2,3).each{ |x| x.must < 50 }
|
42
|
+
@model.solve!.should_not be_nil
|
43
|
+
@store.value.should equal(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should be translated into an element constraint' do
|
47
|
+
@prices[@store].must == @price
|
48
|
+
@model.allow_space_access do
|
49
|
+
Gecode::Raw.should_receive(:element).once.with(
|
50
|
+
an_instance_of(Gecode::Raw::Space),
|
51
|
+
an_instance_of(Gecode::Raw::IntVarArray),
|
52
|
+
@store.bind, @price.bind,
|
53
|
+
Gecode::Raw::ICL_DEF,
|
54
|
+
Gecode::Raw::PK_DEF)
|
55
|
+
end
|
56
|
+
@model.solve!
|
57
|
+
end
|
58
|
+
|
59
|
+
it_should_behave_like(
|
60
|
+
'property that produces int operand by short circuiting equality')
|
61
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
|
+
|
3
|
+
describe Gecode::IntEnum::Equality do
|
4
|
+
before do
|
5
|
+
@model = Gecode::Model.new
|
6
|
+
@vars = @model.int_var_array(4, -2..2)
|
7
|
+
|
8
|
+
@types = [:int_enum]
|
9
|
+
@invoke = lambda do |receiver, hash|
|
10
|
+
receiver.equal(hash)
|
11
|
+
@model.solve!
|
12
|
+
end
|
13
|
+
@expect = lambda do |var, opts, reif_var|
|
14
|
+
Gecode::Raw.should_receive(:rel).once.with(
|
15
|
+
an_instance_of(Gecode::Raw::Space),
|
16
|
+
var, Gecode::Raw::IRT_EQ, *opts)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should constrain elements to be equal' do
|
21
|
+
@vars[1].must == 1
|
22
|
+
@vars.must_be.equal
|
23
|
+
@model.solve!
|
24
|
+
@vars.values.each{ |x| x.should == 1 }
|
25
|
+
end
|
26
|
+
|
27
|
+
it_should_behave_like 'non-reifiable constraint'
|
28
|
+
it_should_behave_like 'non-negatable constraint'
|
29
|
+
end
|