gecoder 0.3.0 → 0.4.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 (56) hide show
  1. data/CHANGES +17 -2
  2. data/README +7 -1
  3. data/Rakefile +4 -0
  4. data/lib/gecoder/interface/constraints/bool/boolean.rb +1 -4
  5. data/lib/gecoder/interface/constraints/int/arithmetic.rb +77 -0
  6. data/lib/gecoder/interface/constraints/int/domain.rb +50 -0
  7. data/lib/gecoder/interface/constraints/int/linear.rb +12 -44
  8. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +72 -0
  9. data/lib/gecoder/interface/constraints/int_enum/channel.rb +32 -0
  10. data/lib/gecoder/interface/constraints/int_enum/count.rb +90 -0
  11. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +3 -8
  12. data/lib/gecoder/interface/constraints/int_enum/element.rb +75 -0
  13. data/lib/gecoder/interface/constraints/int_enum/equality.rb +31 -0
  14. data/lib/gecoder/interface/constraints/int_enum/sort.rb +104 -0
  15. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +6 -0
  16. data/lib/gecoder/interface/constraints/int_var_constraints.rb +2 -0
  17. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +21 -0
  18. data/lib/gecoder/interface/constraints.rb +57 -6
  19. data/lib/gecoder/interface/enum_matrix.rb +64 -0
  20. data/lib/gecoder/interface/enum_wrapper.rb +33 -5
  21. data/lib/gecoder/interface/model.rb +36 -6
  22. data/lib/gecoder/interface.rb +1 -0
  23. data/lib/gecoder/version.rb +4 -0
  24. data/lib/gecoder.rb +1 -0
  25. data/specs/binding_changes.rb +72 -0
  26. data/specs/bool_var.rb +20 -0
  27. data/specs/branch.rb +104 -0
  28. data/specs/constraints/arithmetic.rb +227 -0
  29. data/specs/constraints/boolean.rb +132 -0
  30. data/specs/constraints/channel.rb +55 -0
  31. data/specs/constraints/constraint_helper.rb +48 -0
  32. data/specs/constraints/constraints.rb +28 -0
  33. data/specs/constraints/count.rb +99 -0
  34. data/specs/constraints/distinct.rb +99 -0
  35. data/specs/constraints/domain.rb +56 -0
  36. data/specs/constraints/element.rb +128 -0
  37. data/specs/constraints/equality.rb +30 -0
  38. data/specs/constraints/linear.rb +166 -0
  39. data/specs/constraints/reification_sugar.rb +92 -0
  40. data/specs/constraints/relation.rb +72 -0
  41. data/specs/constraints/sort.rb +173 -0
  42. data/specs/enum_matrix.rb +43 -0
  43. data/specs/enum_wrapper.rb +100 -0
  44. data/specs/int_var.rb +108 -0
  45. data/specs/model.rb +84 -0
  46. data/specs/search.rb +157 -0
  47. data/specs/spec_helper.rb +63 -0
  48. data/specs/tmp +135 -0
  49. data/tasks/all_tasks.rb +1 -0
  50. data/tasks/distribution.rake +64 -0
  51. data/tasks/rcov.rake +17 -0
  52. data/tasks/specs.rake +16 -0
  53. data/tasks/svn.rake +11 -0
  54. data/tasks/website.rake +58 -0
  55. data/vendor/rust/include/rust_conversions.hh +1 -2
  56. metadata +53 -2
@@ -0,0 +1,173 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/constraint_helper'
3
+
4
+ class SortSampleProblem < Gecode::Model
5
+ attr :vars
6
+ attr :sorted
7
+ attr :indices
8
+
9
+ def initialize
10
+ @vars = int_var_array(4, 10..19)
11
+ @sorted = int_var_array(4, 10..19)
12
+ @indices = int_var_array(4, 0..9)
13
+
14
+ # To make it more interesting
15
+ @vars.must_be.distinct
16
+
17
+ branch_on @vars
18
+ end
19
+ end
20
+
21
+ describe Gecode::Constraints::IntEnum::Sort, ' (without :as and :order)' do
22
+ before do
23
+ @model = SortSampleProblem.new
24
+ @vars = @model.vars
25
+ @sorted = @model.sorted
26
+
27
+ @invoke_options = lambda do |hash|
28
+ @vars.must_be.sorted(hash)
29
+ @model.solve!
30
+ end
31
+ @expect_options = lambda do |strength, reif_var|
32
+ if reif_var.nil?
33
+ Gecode::Raw.should_receive(:rel).exactly(@vars.size - 1).times.with(
34
+ @model.active_space,
35
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_LQ,
36
+ an_instance_of(Gecode::Raw::IntVar), strength)
37
+ else
38
+ Gecode::Raw.should_receive(:rel).exactly(@vars.size - 1).times.with(
39
+ @model.active_space,
40
+ an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_LQ,
41
+ an_instance_of(Gecode::Raw::IntVar),
42
+ an_instance_of(Gecode::Raw::BoolVar), strength)
43
+ end
44
+ end
45
+ end
46
+
47
+ it 'should translate into n relation constraints' do
48
+ @expect_options.call(Gecode::Raw::ICL_DEF, nil)
49
+ @invoke_options.call({})
50
+ end
51
+
52
+ it 'should constraint variables to be sorted' do
53
+ @vars.must_be.sorted
54
+ values = @model.solve!.vars.map{ |x| x.val }
55
+ values.should == values.sort
56
+ end
57
+
58
+ it 'should allow negation' do
59
+ @vars.must_not_be.sorted
60
+ @model.solve!
61
+ values = @vars.map{ |x| x.val }
62
+ values.should_not == values.sort
63
+ end
64
+
65
+ it_should_behave_like 'constraint with options'
66
+ end
67
+
68
+ describe Gecode::Constraints::IntEnum::Sort, ' (with :as)' do
69
+ before do
70
+ @model = SortSampleProblem.new
71
+ @vars = @model.vars
72
+ @sorted = @model.sorted
73
+
74
+ # Make it a bit more interesting.
75
+ @vars[0].must > @vars[3] + 1
76
+
77
+ @invoke_options = lambda do |hash|
78
+ @vars.must_be.sorted hash.update(:as => @sorted)
79
+ @model.solve!
80
+ end
81
+ @expect_options = lambda do |strength, reif_var|
82
+ Gecode::Raw.should_receive(:sortedness).once.with(@model.active_space,
83
+ an_instance_of(Gecode::Raw::IntVarArray),
84
+ an_instance_of(Gecode::Raw::IntVarArray), strength)
85
+ end
86
+ end
87
+
88
+ it 'should translate into a sortedness constraints' do
89
+ @expect_options.call(Gecode::Raw::ICL_DEF, nil)
90
+ @invoke_options.call({})
91
+ end
92
+
93
+ it 'should constraint variables to be sorted' do
94
+ @vars.must_be.sorted(:as => @sorted)
95
+ @model.solve!
96
+ values = @sorted.map{ |x| x.val }
97
+ values.should == values.sort
98
+ end
99
+
100
+ it 'should not allow targets that are not int var enums' do
101
+ lambda{ @vars.must_be.sorted(:as => 'hello') }.should raise_error(TypeError)
102
+ end
103
+
104
+ it 'should not allow negation' do
105
+ lambda{ @vars.must_not_be.sorted(:as => @sorted) }.should raise_error(
106
+ Gecode::MissingConstraintError)
107
+ end
108
+
109
+ it_should_behave_like 'constraint with strength option'
110
+ end
111
+
112
+ describe Gecode::Constraints::IntEnum::Sort, ' (with :order)' do
113
+ before do
114
+ @model = SortSampleProblem.new
115
+ @vars = @model.vars
116
+ @sorted = @model.sorted
117
+ @indices = @model.indices
118
+
119
+ # Make it a bit more interesting.
120
+ @vars[0].must > @vars[3] + 1
121
+
122
+ @invoke_options = lambda do |hash|
123
+ @vars.must_be.sorted hash.update(:order => @indices, :as => @sorted)
124
+ @model.solve!
125
+ end
126
+ @expect_options = lambda do |strength, reif_var|
127
+ Gecode::Raw.should_receive(:sortedness).once.with(@model.active_space,
128
+ an_instance_of(Gecode::Raw::IntVarArray),
129
+ an_instance_of(Gecode::Raw::IntVarArray),
130
+ an_instance_of(Gecode::Raw::IntVarArray), strength)
131
+ end
132
+ end
133
+
134
+ it 'should translate into a sortedness constraints' do
135
+ @expect_options.call(Gecode::Raw::ICL_DEF, nil)
136
+ @invoke_options.call({})
137
+ end
138
+
139
+ it 'should translate into a sortedness constraints, even without a target' do
140
+ @expect_options.call(Gecode::Raw::ICL_DEF, nil)
141
+ @vars.must_be.sorted(:order => @indices)
142
+ @model.solve!
143
+ end
144
+
145
+ it 'should constraint variables to be sorted with the specified indices' do
146
+ @vars.must_be.sorted(:as => @sorted, :order => @indices)
147
+ @model.solve!
148
+ sorted_values = @sorted.map{ |x| x.val }
149
+ sorted_values.should == sorted_values.sort
150
+ expected_indices = @vars.map{ |v| sorted_values.index(v.val) }
151
+ @indices.map{ |i| i.val }.should == expected_indices
152
+ end
153
+
154
+ it 'should not allow targets that are not int var enums' do
155
+ lambda do
156
+ @vars.must_be.sorted(:as => 'hello', :order => @indices)
157
+ end.should raise_error(TypeError)
158
+ end
159
+
160
+ it 'should not allow order that are not int var enums' do
161
+ lambda do
162
+ @vars.must_be.sorted(:as => @sorted, :order => 'hello')
163
+ end.should raise_error(TypeError)
164
+ end
165
+
166
+ it 'should not allow negation' do
167
+ lambda do
168
+ @vars.must_not_be.sorted(:as => @sorted, :order => @indices)
169
+ end.should raise_error(Gecode::MissingConstraintError)
170
+ end
171
+
172
+ it_should_behave_like 'constraint with strength option'
173
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Gecode::Util::EnumMatrix do
4
+ before do
5
+ @matrix = Gecode::Util::EnumMatrix[[0, 1], [1, 0]]
6
+ end
7
+
8
+ it 'should be enumerable' do
9
+ @matrix.should be_kind_of(Enumerable)
10
+ end
11
+
12
+ it 'should produce rows that are enumerable' do
13
+ @matrix.row(0).should be_kind_of(Enumerable)
14
+ @matrix.row(0).inject([]){ |arr, e| arr << e }.should == [0, 1]
15
+ end
16
+
17
+ it 'should produce columns that are enumerable' do
18
+ @matrix.column(0).should be_kind_of(Enumerable)
19
+ end
20
+
21
+ it 'should produce submatrices that are enumerable' do
22
+ @matrix.minor(0,1,0,1).should be_kind_of(Enumerable)
23
+ end
24
+ end
25
+
26
+ describe Gecode::Util::EnumMatrix, ' (when wrapped)' do
27
+ before do
28
+ @model = Gecode::Model.new
29
+ @matrix = @model.wrap_enum(Gecode::Util::EnumMatrix[[0, 1], [1, 0]])
30
+ end
31
+
32
+ it 'should produce rows that are wrapped' do
33
+ @matrix.row(0).should respond_to(:model)
34
+ end
35
+
36
+ it 'should produce columns that are enumerable' do
37
+ @matrix.column(0).should respond_to(:model)
38
+ end
39
+
40
+ it 'should produce submatrices that are enumerable' do
41
+ @matrix.minor(0,1,0,1).should respond_to(:model)
42
+ end
43
+ end
@@ -0,0 +1,100 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Gecode::Model, ' (enum wrapping)' do
4
+ before do
5
+ @model = Gecode::Model.new
6
+ @bool = @model.bool_var
7
+ @int = @model.int_var(1..2)
8
+ end
9
+
10
+ it 'should only allow enumerables to be wrapped' do
11
+ lambda do
12
+ @model.wrap_enum(17)
13
+ end.should raise_error(TypeError)
14
+ end
15
+
16
+ it 'should allow enumerables of bool variables to be wrapped' do
17
+ lambda do
18
+ enum = [@bool]
19
+ @model.wrap_enum(enum)
20
+ end.should_not raise_error
21
+ end
22
+
23
+ it 'should allow enumerables of int variables to be wrapped' do
24
+ lambda do
25
+ enum = [@int]
26
+ @model.wrap_enum(enum)
27
+ end.should_not raise_error
28
+ end
29
+
30
+ it 'should allow enumerables of fixnums to be wrapped' do
31
+ lambda do
32
+ enum = [17]
33
+ @model.wrap_enum(enum)
34
+ end.should_not raise_error
35
+ end
36
+
37
+ it 'should not allow empty enumerables to be wrapped' do
38
+ lambda do
39
+ @model.wrap_enum([])
40
+ end.should raise_error(ArgumentError)
41
+ end
42
+
43
+ it 'should not allow enumerables without variables or fixnums to be wrapped' do
44
+ lambda do
45
+ @model.wrap_enum(['foo'])
46
+ end.should raise_error(TypeError)
47
+ end
48
+
49
+ it 'should not allow enumerables with only some variables to be wrapped' do
50
+ lambda do
51
+ enum = [@bool, 'foo']
52
+ @model.wrap_enum(enum)
53
+ end.should raise_error(TypeError)
54
+ end
55
+
56
+ it 'should not allow enumerables with mixed types of variables to be wrapped' do
57
+ lambda do
58
+ enum = [@bool, @int]
59
+ @model.wrap_enum(enum)
60
+ end.should raise_error(TypeError)
61
+ end
62
+ end
63
+
64
+ describe Gecode::IntEnumMethods do
65
+ before do
66
+ @model = Gecode::Model.new
67
+ @int_enum = @model.int_var_array(3, 0..1)
68
+ end
69
+
70
+ it 'should convert to an int var array' do
71
+ @int_enum.to_int_var_array.should be_kind_of(Gecode::Raw::IntVarArray)
72
+ end
73
+
74
+ it 'should compute the smallest domain range' do
75
+ @int_enum.domain_range.should == (0..1)
76
+ (@int_enum << @model.int_var(-4..4)).domain_range.should == (-4..4)
77
+ end
78
+ end
79
+
80
+ describe Gecode::BoolEnumMethods do
81
+ before do
82
+ @model = Gecode::Model.new
83
+ @int_enum = @model.bool_var_array(3)
84
+ end
85
+
86
+ it 'should convert to a bool var array' do
87
+ @int_enum.to_bool_var_array.should be_kind_of(Gecode::Raw::BoolVarArray)
88
+ end
89
+ end
90
+
91
+ describe Gecode::FixnumEnumMethods do
92
+ before do
93
+ @model = Gecode::Model.new
94
+ @enum = @model.instance_eval{ wrap_enum([7, 14, 17, 4711]) }
95
+ end
96
+
97
+ it 'should compute the smallest domain range' do
98
+ @enum.domain_range.should == (7..4711)
99
+ end
100
+ end
data/specs/int_var.rb ADDED
@@ -0,0 +1,108 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe 'non-empty int variable', :shared => true do
4
+ it 'should have min equal to the lower domain bound' do
5
+ @var.min.should equal(@domain.min)
6
+ end
7
+
8
+ it 'should have max equal to the upper domain bound' do
9
+ @var.max.should equal(@domain.max)
10
+ end
11
+
12
+ it 'should have size equal to the domain size' do
13
+ @var.size.should equal(@domain.size)
14
+ end
15
+
16
+ it 'should contain every element in its domain' do
17
+ @domain.each do |i|
18
+ @var.should be_in(i)
19
+ end
20
+ end
21
+
22
+ it 'should not contain elements outside its domain' do
23
+ @var.should_not be_in(@domain.min - 1)
24
+ @var.should_not be_in(@domain.max + 1)
25
+ end
26
+
27
+ it 'should have a width equal to the domain width' do
28
+ @var.width.should equal(@domain.max - @domain.min + 1)
29
+ end
30
+
31
+ it 'should give a NoMethodError when calling a method that doesn\'t exist' do
32
+ lambda{ @var.this_method_does_not_exists }.should raise_error(NoMethodError)
33
+ end
34
+
35
+ it 'should have a zero degree' do
36
+ @var.degree.should be_zero
37
+ end
38
+ end
39
+
40
+ describe Gecode::FreeIntVar, ' (with range domain of size > 1)' do
41
+ before do
42
+ @range = -4..3
43
+ @domain = @range.to_a
44
+ model = Gecode::Model.new
45
+ @var = model.int_var(@range)
46
+ end
47
+
48
+ it_should_behave_like 'non-empty int variable'
49
+
50
+ it 'should not be assigned' do
51
+ @var.should_not be_assigned
52
+ end
53
+
54
+ it 'should have a range domain' do
55
+ @var.should be_range
56
+ end
57
+ end
58
+
59
+ describe Gecode::FreeIntVar, ' (defined with three-dot range)' do
60
+ before do
61
+ @range = -4...3
62
+ @domain = @range.to_a
63
+ model = Gecode::Model.new
64
+ @var = model.int_var(@range)
65
+ end
66
+
67
+ it_should_behave_like 'non-empty int variable'
68
+ end
69
+
70
+ describe Gecode::FreeIntVar, ' (with non-range domain of size > 1)' do
71
+ before do
72
+ @domain = [-3, -2, -1, 1]
73
+ model = Gecode::Model.new
74
+ @var = model.int_var(*@domain)
75
+ end
76
+
77
+ it_should_behave_like 'non-empty int variable'
78
+
79
+ it 'should not be assigned' do
80
+ @var.should_not be_assigned
81
+ end
82
+
83
+ it 'should not be a range domain' do
84
+ @var.should_not be_range
85
+ end
86
+
87
+ it 'should not contain the domain\'s holes' do
88
+ @var.should_not be_in(0)
89
+ end
90
+ end
91
+
92
+ describe Gecode::FreeIntVar, '(with a domain of size 1)' do
93
+ before do
94
+ @domain = [1]
95
+ model = Gecode::Model.new
96
+ @var = model.int_var(*@domain)
97
+ end
98
+
99
+ it_should_behave_like 'non-empty int variable'
100
+
101
+ it 'should be assigned' do
102
+ @var.should be_assigned
103
+ end
104
+
105
+ it 'should be a range domain' do
106
+ @var.should be_range
107
+ end
108
+ end
data/specs/model.rb ADDED
@@ -0,0 +1,84 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Gecode::Model, ' (integer creation)' do
4
+ before do
5
+ @model = Gecode::Model.new
6
+ end
7
+
8
+ it 'should allow the creation of int variables with range' do
9
+ range = 0..3
10
+ @model.int_var(range).should have_domain(range)
11
+ end
12
+
13
+ # This currently fails, see specs/int_var for an explanation.
14
+ it 'should allow the creation of int variables with non-range domains' do
15
+ domain = [1, 3, 5]
16
+ @model.int_var(*domain).should have_domain(domain)
17
+ end
18
+
19
+ it 'should allow the creation of int variables with single element domains' do
20
+ domain = 3
21
+ @model.int_var(domain).should have_domain([domain])
22
+ end
23
+
24
+ it 'should not accept empty domains' do
25
+ lambda{ @model.int_var }.should raise_error(ArgumentError)
26
+ lambda{ @model.int_var_array(1) }.should raise_error(ArgumentError)
27
+ end
28
+
29
+ it 'should allow the creation of int-var arrays with range domains' do
30
+ range = 0..3
31
+ count = 5
32
+ vars = @model.int_var_array(count, range)
33
+ vars.size.should equal(count)
34
+ vars.each{ |var| var.should have_domain(range) }
35
+ end
36
+
37
+ it 'should allow the creation of int-var arrays with non-range domains' do
38
+ domain = [1,3,5]
39
+ count = 5
40
+ vars = @model.int_var_array(count, *domain)
41
+ vars.size.should equal(count)
42
+ vars.each{ |var| var.should have_domain(domain) }
43
+ end
44
+
45
+ it 'should allow the creation of int-var matrices with range domains' do
46
+ range = 0..3
47
+ rows = 5
48
+ columns = 4
49
+ vars = @model.int_var_matrix(rows, columns, range)
50
+ vars.row_size.should equal(rows)
51
+ vars.column_size.should equal(columns)
52
+ vars.each{ |var| var.should have_domain(range) }
53
+ end
54
+
55
+ it 'should allow the creation of int-var matrices with non-range domains' do
56
+ domain = [1,3,5]
57
+ rows = 5
58
+ columns = 4
59
+ vars = @model.int_var_matrix(rows, columns, *domain)
60
+ vars.row_size.should equal(rows)
61
+ vars.column_size.should equal(columns)
62
+ vars.each{ |var| var.should have_domain(domain) }
63
+ end
64
+ end
65
+
66
+ describe Gecode::Model, ' (bool creation)' do
67
+ before do
68
+ @model = Gecode::Model.new
69
+ end
70
+
71
+ it 'should allow the creation of boolean variables' do
72
+ @model.bool_var.should_not be_nil
73
+ end
74
+
75
+ it 'should allow the creation of arrays of boolean variables' do
76
+ @model.bool_var_array(3).size.should equal(3)
77
+ end
78
+
79
+ it 'should allow the creation of matrices of boolean variables' do
80
+ matrix = @model.bool_var_matrix(3, 4)
81
+ matrix.row_size.should equal(3)
82
+ matrix.column_size.should equal(4)
83
+ end
84
+ end
data/specs/search.rb ADDED
@@ -0,0 +1,157 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'set'
3
+
4
+ class SampleProblem < Gecode::Model
5
+ attr :var
6
+ attr :array
7
+ attr :hash
8
+ attr :nested_enum
9
+
10
+ def initialize(domain)
11
+ vars = self.int_var_array(1,domain)
12
+ @var = vars.first
13
+ @var.must > 1
14
+ @array = [@var]
15
+ @hash = {:a => var}
16
+ @nested_enum = [1,2,[@var],[7, {:b => var}]]
17
+
18
+ branch_on vars, :variable => :smallest_size, :value => :min
19
+ end
20
+ end
21
+
22
+ describe Gecode::Model, ' (with multiple solutions)' do
23
+ before do
24
+ @domain = 0..3
25
+ @solved_domain = [2]
26
+ @model = SampleProblem.new(@domain)
27
+ end
28
+
29
+ it 'should pass a solution to the block given in #solution' do
30
+ @model.solution do |s|
31
+ s.var.should have_domain(@solved_domain)
32
+ end
33
+ end
34
+
35
+ it 'should only evaluate the block for one solution in #solution' do
36
+ i = 0
37
+ @model.solution{ |s| i += 1 }
38
+ i.should equal(1)
39
+ end
40
+
41
+ it 'should return the result of the block when calling #solution' do
42
+ @model.solution{ |s| 'test' }.should == 'test'
43
+ end
44
+
45
+ it 'should pass every solution to #each_solution' do
46
+ solutions = []
47
+ @model.each_solution do |s|
48
+ solutions << s.var.val
49
+ end
50
+ Set.new(solutions).should == Set.new([2,3])
51
+ end
52
+ end
53
+
54
+ describe Gecode::Model, ' (after #solve!)' do
55
+ before do
56
+ @domain = 0..3
57
+ @solved_domain = [2]
58
+ @model = SampleProblem.new(@domain)
59
+ @model.solve!
60
+ end
61
+
62
+ it 'should have updated the variables domains' do
63
+ @model.var.should have_domain(@solved_domain)
64
+ end
65
+
66
+ it 'should have updated variables in arrays' do
67
+ @model.array.first.should have_domain(@solved_domain)
68
+ end
69
+
70
+ it 'should have updated variables in hashes' do
71
+ @model.hash.values.first.should have_domain(@solved_domain)
72
+ end
73
+
74
+ it 'should have updated variables in nested enums' do
75
+ enum = @model.solve!.nested_enum
76
+ enum[2].first.should have_domain(@solved_domain)
77
+ enum[3][1][:b].should have_domain(@solved_domain)
78
+
79
+ enum = @model.nested_enum
80
+ enum[2].first.should have_domain(@solved_domain)
81
+ enum[3][1][:b].should have_domain(@solved_domain)
82
+ end
83
+ end
84
+
85
+ describe 'reset model', :shared => true do
86
+ it 'should have reset variables' do
87
+ @model.var.should have_domain(@reset_domain)
88
+ end
89
+
90
+ it 'should have reset variables in nested enums' do
91
+ enum = @model.nested_enum
92
+ enum[2].first.should have_domain(@reset_domain)
93
+ enum[3][1][:b].should have_domain(@reset_domain)
94
+ end
95
+ end
96
+
97
+ describe Gecode::Model, ' (after #reset!)' do
98
+ before do
99
+ @domain = 0..3
100
+ @reset_domain = 2..3
101
+ @model = SampleProblem.new(@domain)
102
+ @model.solve!
103
+ @model.reset!
104
+ end
105
+
106
+ it_should_behave_like 'reset model'
107
+ end
108
+
109
+ describe Gecode::Model, ' (after #solution)' do
110
+ before do
111
+ @domain = 0..3
112
+ @reset_domain = 2..3
113
+ @model = SampleProblem.new(@domain)
114
+ @model.solution{ |s| }
115
+ end
116
+
117
+ it_should_behave_like 'reset model'
118
+ end
119
+
120
+ describe Gecode::Model, ' (after #each_solution)' do
121
+ before do
122
+ @domain = 0..3
123
+ @reset_domain = 2..3
124
+ @model = SampleProblem.new(@domain)
125
+ @model.each_solution{ |s| }
126
+ end
127
+
128
+ it_should_behave_like 'reset model'
129
+ end
130
+
131
+ describe Gecode::Model, ' (without solution)' do
132
+ before do
133
+ @domain = 0..3
134
+ @model = SampleProblem.new(@domain)
135
+ @model.var.must < 0
136
+ end
137
+
138
+ it 'should return nil when calling #solution' do
139
+ @model.var.must < 0
140
+ @model.solution{ |s| 'test' }.should be_nil
141
+ end
142
+
143
+ it 'should return nil when calling #solve!' do
144
+ @model.solve!.should be_nil
145
+ end
146
+ end
147
+
148
+ describe Gecode::Model, ' (without constraints)' do
149
+ before do
150
+ @model = Gecode::Model.new
151
+ @x = @model.int_var(0..1)
152
+ end
153
+
154
+ it 'should produce a solution' do
155
+ @model.solve!.should_not be_nil
156
+ end
157
+ end