gecoder 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +6 -0
- data/README +1 -1
- data/THANKS +18 -0
- data/example/equation_system.rb +3 -1
- data/example/magic_sequence.rb +3 -1
- data/example/queens.rb +3 -1
- data/example/send_more_money.rb +24 -30
- data/example/send_most_money.rb +15 -26
- data/example/square_tiling.rb +3 -1
- data/example/sudoku-set.rb +3 -1
- data/lib/gecoder/bindings.rb +7 -5
- data/lib/gecoder/bindings/bindings.rb +8 -8
- data/lib/gecoder/interface.rb +4 -2
- data/lib/gecoder/interface/binding_changes.rb +1 -1
- data/lib/gecoder/interface/branch.rb +1 -1
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +4 -4
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +2 -2
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +1 -1
- data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +2 -2
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +5 -5
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +4 -4
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +2 -2
- data/lib/gecoder/interface/constraints/selected_set/select.rb +8 -8
- data/lib/gecoder/interface/constraints/set_enum/{select.rb → element.rb} +10 -10
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +5 -5
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +2 -2
- data/lib/gecoder/interface/{model_sugar.rb → convenience.rb} +19 -4
- data/lib/gecoder/interface/enum_wrapper.rb +1 -1
- data/lib/gecoder/interface/{model.rb → mixin.rb} +93 -60
- data/lib/gecoder/interface/search.rb +23 -22
- data/lib/gecoder/version.rb +1 -1
- data/specs/branch.rb +5 -3
- data/specs/constraints/bool/boolean.rb +3 -1
- data/specs/constraints/bool/linear.rb +3 -1
- data/specs/constraints/bool_enum/bool_enum_relation.rb +3 -1
- data/specs/constraints/bool_enum/channel.rb +3 -1
- data/specs/constraints/fixnum_enum/element.rb +3 -1
- data/specs/constraints/int/arithmetic.rb +3 -1
- data/specs/constraints/int/channel.rb +3 -1
- data/specs/constraints/int/linear.rb +3 -1
- data/specs/constraints/int/linear_properties.rb +3 -1
- data/specs/constraints/int_enum/arithmetic.rb +3 -1
- data/specs/constraints/int_enum/channel.rb +3 -1
- data/specs/constraints/int_enum/count.rb +3 -1
- data/specs/constraints/int_enum/distinct.rb +3 -1
- data/specs/constraints/int_enum/element.rb +3 -1
- data/specs/constraints/int_enum/sort.rb +3 -1
- data/specs/constraints/property_helper.rb +10 -10
- data/specs/constraints/reification_sugar.rb +3 -1
- data/specs/constraints/selected_set/select.rb +6 -5
- data/specs/constraints/selected_set/select_properties.rb +12 -10
- data/specs/constraints/set/channel.rb +3 -1
- data/specs/constraints/set/domain.rb +4 -4
- data/specs/constraints/set/relation.rb +4 -4
- data/specs/constraints/set_enum/channel.rb +3 -1
- data/specs/constraints/set_enum/distinct.rb +3 -1
- data/specs/constraints/set_enum/{select.rb → element.rb} +13 -9
- data/specs/enum_wrapper.rb +1 -1
- data/specs/mixin.rb +78 -0
- data/specs/model.rb +5 -5
- data/specs/search.rb +20 -14
- data/specs/selected_set.rb +3 -3
- data/specs/set_elements.rb +2 -2
- data/tasks/distribution.rake +25 -4
- metadata +15 -12
- data/example/money.rb +0 -36
@@ -7,14 +7,14 @@ module Gecode
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
module Mixin
|
11
11
|
# Finds the first solution to the modelled problem and updates the variables
|
12
12
|
# to that solution. The found solution is also returned. Raises
|
13
13
|
# Gecode::NoSolutionError if no solution can be found.
|
14
14
|
def solve!
|
15
15
|
dfs = dfs_engine
|
16
16
|
space = dfs.next
|
17
|
-
@
|
17
|
+
@gecoder_mixin_statistics = dfs.statistics
|
18
18
|
raise Gecode::NoSolutionError if space.nil?
|
19
19
|
self.active_space = space
|
20
20
|
return self
|
@@ -24,7 +24,7 @@ module Gecode
|
|
24
24
|
# propagation might have been performed). Returns the reset model.
|
25
25
|
def reset!
|
26
26
|
self.active_space = base_space
|
27
|
-
@
|
27
|
+
@gecoder_mixin_statistics = nil
|
28
28
|
return self
|
29
29
|
end
|
30
30
|
|
@@ -48,7 +48,7 @@ module Gecode
|
|
48
48
|
next_solution = nil
|
49
49
|
while not (next_solution = dfs.next).nil?
|
50
50
|
self.active_space = next_solution
|
51
|
-
@
|
51
|
+
@gecoder_mixin_statistics = dfs.statistics
|
52
52
|
yield self
|
53
53
|
end
|
54
54
|
self.reset!
|
@@ -64,26 +64,27 @@ module Gecode
|
|
64
64
|
# [:commits] The number of commit operations performed.
|
65
65
|
# [:memory] The peak memory allocated to Gecode.
|
66
66
|
def search_stats
|
67
|
-
return nil if @
|
67
|
+
return nil if @gecoder_mixin_statistics.nil?
|
68
68
|
|
69
69
|
return {
|
70
|
-
:propagations => @
|
71
|
-
:failures => @
|
72
|
-
:clones => @
|
73
|
-
:commits => @
|
74
|
-
:memory => @
|
70
|
+
:propagations => @gecoder_mixin_statistics.propagate,
|
71
|
+
:failures => @gecoder_mixin_statistics.fail,
|
72
|
+
:clones => @gecoder_mixin_statistics.clone,
|
73
|
+
:commits => @gecoder_mixin_statistics.commit,
|
74
|
+
:memory => @gecoder_mixin_statistics.memory
|
75
75
|
}
|
76
76
|
end
|
77
77
|
|
78
|
-
# Finds the optimal solution. Optimality is defined by the provided
|
79
|
-
# which is given
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
# the
|
78
|
+
# Finds the optimal solution. Optimality is defined by the provided
|
79
|
+
# block which is given two parameters, the model and the best
|
80
|
+
# solution found so far to the problem. The block should constrain
|
81
|
+
# the model so that that only "better" solutions can be new
|
82
|
+
# solutions. For instance if one wants to optimize a variable named
|
83
|
+
# price (accessible from the model) to be as low as possible then
|
84
|
+
# one should write the following.
|
84
85
|
#
|
85
86
|
# model.optimize! do |model, best_so_far|
|
86
|
-
# model.price.must < best_so_far.price.
|
87
|
+
# model.price.must < best_so_far.price.value
|
87
88
|
# end
|
88
89
|
#
|
89
90
|
# Raises Gecode::NoSolutionError if no solution can be found.
|
@@ -92,12 +93,12 @@ module Gecode
|
|
92
93
|
perform_queued_gecode_interactions
|
93
94
|
|
94
95
|
# Set the method used for constrain calls by the BAB-search.
|
95
|
-
|
96
|
+
Mixin.constrain_proc = lambda do |home_space, best_space|
|
96
97
|
self.active_space = best_space
|
97
|
-
@
|
98
|
+
@gecoder_mixin_variable_creation_space = home_space
|
98
99
|
yield(self, self)
|
99
100
|
self.active_space = home_space
|
100
|
-
@
|
101
|
+
@gecoder_mixin_variable_creation_space = nil
|
101
102
|
|
102
103
|
perform_queued_gecode_interactions
|
103
104
|
end
|
@@ -114,10 +115,10 @@ module Gecode
|
|
114
115
|
until (previous_solution = bab.next).nil?
|
115
116
|
result = previous_solution
|
116
117
|
end
|
117
|
-
@
|
118
|
+
@gecoder_mixin_statistics = bab.statistics
|
118
119
|
|
119
120
|
# Reset the method used constrain calls and return the result.
|
120
|
-
|
121
|
+
Mixin.constrain_proc = nil
|
121
122
|
raise Gecode::NoSolutionError if result.nil?
|
122
123
|
|
123
124
|
# Switch to the result.
|
data/lib/gecoder/version.rb
CHANGED
data/specs/branch.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
class BranchSampleProblem
|
3
|
+
class BranchSampleProblem
|
4
|
+
include Gecode::Mixin
|
5
|
+
|
4
6
|
attr :vars
|
5
7
|
attr :bools
|
6
8
|
attr :sets
|
@@ -12,7 +14,7 @@ class BranchSampleProblem < Gecode::Model
|
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
|
-
describe Gecode::
|
17
|
+
describe Gecode::Mixin, ' (integer branch)' do
|
16
18
|
before do
|
17
19
|
@model = BranchSampleProblem.new
|
18
20
|
@vars = @model.vars
|
@@ -112,7 +114,7 @@ describe Gecode::Model, ' (integer branch)' do
|
|
112
114
|
end
|
113
115
|
end
|
114
116
|
|
115
|
-
describe Gecode::
|
117
|
+
describe Gecode::Mixin, ' (set branch)' do
|
116
118
|
before do
|
117
119
|
@model = BranchSampleProblem.new
|
118
120
|
@sets = @model.sets
|
@@ -3,7 +3,9 @@ require File.dirname(__FILE__) + '/../constraint_helper'
|
|
3
3
|
# This is neither an operand or a constraint spec. It is mostly a sanity
|
4
4
|
# check.
|
5
5
|
|
6
|
-
class LinearSampleProblem
|
6
|
+
class LinearSampleProblem
|
7
|
+
include Gecode::Mixin
|
8
|
+
|
7
9
|
attr :x
|
8
10
|
attr :y
|
9
11
|
attr :z
|
@@ -30,14 +30,14 @@ require File.dirname(__FILE__) + '/../spec_helper'
|
|
30
30
|
# Requires @operand and @model.
|
31
31
|
describe 'int var operand', :shared => true do
|
32
32
|
it 'should implement #model' do
|
33
|
-
@operand.model.should be_kind_of(Gecode::
|
33
|
+
@operand.model.should be_kind_of(Gecode::Mixin)
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'should implement #to_int_var' do
|
37
37
|
int_var = @operand.to_int_var
|
38
38
|
int_var.should be_kind_of(Gecode::IntVar)
|
39
39
|
@model.solve!
|
40
|
-
(int_var.min..int_var.max).should_not equal(Gecode::
|
40
|
+
(int_var.min..int_var.max).should_not equal(Gecode::Mixin::LARGEST_INT_DOMAIN)
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'should implement #must' do
|
@@ -50,7 +50,7 @@ end
|
|
50
50
|
# Requires @operand and @model.
|
51
51
|
describe 'bool var operand', :shared => true do
|
52
52
|
it 'should implement #model' do
|
53
|
-
@operand.model.should be_kind_of(Gecode::
|
53
|
+
@operand.model.should be_kind_of(Gecode::Mixin)
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'should implement #to_bool_var' do
|
@@ -68,7 +68,7 @@ end
|
|
68
68
|
# Requires @operand and @model.
|
69
69
|
describe 'set var operand', :shared => true do
|
70
70
|
it 'should implement #model' do
|
71
|
-
@operand.model.should be_kind_of(Gecode::
|
71
|
+
@operand.model.should be_kind_of(Gecode::Mixin)
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'should implement #to_set_var' do
|
@@ -76,7 +76,7 @@ describe 'set var operand', :shared => true do
|
|
76
76
|
set_var.should be_kind_of(Gecode::SetVar)
|
77
77
|
@model.solve!
|
78
78
|
((set_var.lower_bound == []) &&
|
79
|
-
(set_var.upper_bound == Gecode::
|
79
|
+
(set_var.upper_bound == Gecode::Mixin::LARGEST_SET_BOUND)).should_not(
|
80
80
|
be_true)
|
81
81
|
end
|
82
82
|
|
@@ -108,7 +108,7 @@ describe 'property that produces int operand', :shared => true do
|
|
108
108
|
operand = @select_property.call(*operands)
|
109
109
|
|
110
110
|
# Test the same invariants as in the test for int var operands.
|
111
|
-
operand.model.should be_kind_of(Gecode::
|
111
|
+
operand.model.should be_kind_of(Gecode::Mixin)
|
112
112
|
|
113
113
|
int_var = operand.to_int_var
|
114
114
|
int_var.should be_kind_of(Gecode::IntVar)
|
@@ -128,7 +128,7 @@ describe 'property that produces bool operand', :shared => true do
|
|
128
128
|
operand = @select_property.call(*operands)
|
129
129
|
|
130
130
|
# Test the same invariants as in the test for bool var operands.
|
131
|
-
operand.model.should be_kind_of(Gecode::
|
131
|
+
operand.model.should be_kind_of(Gecode::Mixin)
|
132
132
|
|
133
133
|
bool_var = operand.to_bool_var
|
134
134
|
bool_var.should be_kind_of(Gecode::BoolVar)
|
@@ -148,7 +148,7 @@ describe 'property that produces set operand', :shared => true do
|
|
148
148
|
operand = @select_property.call(*operands)
|
149
149
|
|
150
150
|
# Test the same invariants as in the test for int var operands.
|
151
|
-
operand.model.should be_kind_of(Gecode::
|
151
|
+
operand.model.should be_kind_of(Gecode::Mixin)
|
152
152
|
|
153
153
|
set_var = operand.to_set_var
|
154
154
|
set_var.should be_kind_of(Gecode::SetVar)
|
@@ -178,7 +178,7 @@ describe 'property that produces int operand by short circuiting equality', :sha
|
|
178
178
|
@selected_property.must == indirect_int_op
|
179
179
|
@model.solve!
|
180
180
|
|
181
|
-
direct_int_var.should_not have_domain(Gecode::
|
181
|
+
direct_int_var.should_not have_domain(Gecode::Mixin::LARGEST_INT_DOMAIN)
|
182
182
|
direct_int_var.should have_domain(indirect_int_op.domain)
|
183
183
|
end
|
184
184
|
|
@@ -282,7 +282,7 @@ describe 'property that produces int operand by short circuiting relations', :sh
|
|
282
282
|
@selected_property.must.method(relation).call indirect_int_var
|
283
283
|
@model.solve!
|
284
284
|
|
285
|
-
direct_int_var.should_not have_domain(Gecode::
|
285
|
+
direct_int_var.should_not have_domain(Gecode::Mixin::LARGEST_INT_DOMAIN)
|
286
286
|
direct_int_var.should have_domain(indirect_int_var.domain)
|
287
287
|
end
|
288
288
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../constraint_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class DisjointSelectSampleProblem
|
4
|
+
include Gecode::Mixin
|
5
|
+
|
4
6
|
attr :sets
|
5
7
|
attr :set
|
6
8
|
attr :target
|
@@ -16,11 +18,11 @@ class SelectionSampleProblem < Gecode::Model
|
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
|
-
describe Gecode::SetEnum::
|
21
|
+
describe Gecode::SetEnum::Element, ' (disjoint)' do
|
20
22
|
include GecodeR::Specs::SetHelper
|
21
23
|
|
22
24
|
before do
|
23
|
-
@model =
|
25
|
+
@model = DisjointSelectSampleProblem.new
|
24
26
|
@sets = @model.sets
|
25
27
|
@set = @model.set
|
26
28
|
@target = @model.target
|
@@ -33,7 +35,7 @@ describe Gecode::SetEnum::Select, ' (disjoint)' do
|
|
33
35
|
end
|
34
36
|
@expect = lambda do |var, opts, reif_var|
|
35
37
|
set_enum, set = var
|
36
|
-
Gecode::Raw.should_receive(:
|
38
|
+
Gecode::Raw.should_receive(:elementDisjoint).once.with(
|
37
39
|
an_instance_of(Gecode::Raw::Space),
|
38
40
|
set_enum, set)
|
39
41
|
end
|
@@ -53,4 +55,3 @@ describe Gecode::SetEnum::Select, ' (disjoint)' do
|
|
53
55
|
it_should_behave_like 'non-reifiable set constraint'
|
54
56
|
it_should_behave_like 'non-negatable constraint'
|
55
57
|
end
|
56
|
-
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../property_helper'
|
2
2
|
|
3
|
-
class SelectionSampleProblem
|
3
|
+
class SelectionSampleProblem
|
4
|
+
include Gecode::Mixin
|
5
|
+
|
4
6
|
attr :sets
|
5
7
|
attr :set
|
6
8
|
attr :target
|
@@ -16,7 +18,7 @@ class SelectionSampleProblem < Gecode::Model
|
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
|
-
describe Gecode::SelectedSet::
|
21
|
+
describe Gecode::SelectedSet::Element, ' (union)' do
|
20
22
|
include GecodeR::Specs::SetHelper
|
21
23
|
|
22
24
|
before do
|
@@ -44,8 +46,8 @@ describe Gecode::SelectedSet::Select, ' (union)' do
|
|
44
46
|
(union - [5,7,9]).should be_empty
|
45
47
|
end
|
46
48
|
|
47
|
-
it 'should translate into a
|
48
|
-
Gecode::Raw.should_receive(:
|
49
|
+
it 'should translate into a elements union constraint' do
|
50
|
+
Gecode::Raw.should_receive(:elementsUnion)
|
49
51
|
@sets[@set].union.must_be.subset_of([5,7,9])
|
50
52
|
@model.solve!
|
51
53
|
end
|
@@ -54,7 +56,7 @@ describe Gecode::SelectedSet::Select, ' (union)' do
|
|
54
56
|
'property that produces set operand by short circuiting equality')
|
55
57
|
end
|
56
58
|
|
57
|
-
describe Gecode::SetEnum::
|
59
|
+
describe Gecode::SetEnum::Element, ' (intersection)' do
|
58
60
|
include GecodeR::Specs::SetHelper
|
59
61
|
|
60
62
|
before do
|
@@ -84,8 +86,8 @@ describe Gecode::SetEnum::Select, ' (intersection)' do
|
|
84
86
|
(intersection - [5,7,9]).should be_empty
|
85
87
|
end
|
86
88
|
|
87
|
-
it 'should translate into a
|
88
|
-
Gecode::Raw.should_receive(:
|
89
|
+
it 'should translate into a elements intersection constraint' do
|
90
|
+
Gecode::Raw.should_receive(:elementsInter)
|
89
91
|
@sets[@set].intersection.must_be.subset_of([5,7,9])
|
90
92
|
@model.solve!
|
91
93
|
end
|
@@ -94,7 +96,7 @@ describe Gecode::SetEnum::Select, ' (intersection)' do
|
|
94
96
|
'property that produces set operand by short circuiting equality')
|
95
97
|
end
|
96
98
|
|
97
|
-
describe Gecode::SelectedSet::
|
99
|
+
describe Gecode::SelectedSet::Element, ' (intersection with universe)' do
|
98
100
|
include GecodeR::Specs::SetHelper
|
99
101
|
|
100
102
|
before do
|
@@ -132,8 +134,8 @@ describe Gecode::SelectedSet::Select, ' (intersection with universe)' do
|
|
132
134
|
(intersection - [1,2]).should be_empty
|
133
135
|
end
|
134
136
|
|
135
|
-
it 'should translate into a
|
136
|
-
Gecode::Raw.should_receive(:
|
137
|
+
it 'should translate into a elements intersection constraint' do
|
138
|
+
Gecode::Raw.should_receive(:elementsInter)
|
137
139
|
@sets[@set].intersection(:with => 1..2).must_be.subset_of([5,7,9])
|
138
140
|
@model.solve!
|
139
141
|
end
|