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,8 +1,8 @@
1
1
  require 'matrix'
2
2
 
3
- module Gecode::Util
3
+ module Gecode::Util #:nodoc:
4
4
  # Methods that make a matrix an enumerable.
5
- module MatrixEnumMethods
5
+ module MatrixEnumMethods #:nodoc:
6
6
  include Enumerable
7
7
 
8
8
  # Iterates over every element in the matrix.
@@ -16,7 +16,7 @@ module Gecode::Util
16
16
  end
17
17
 
18
18
  # Extends Matrix so that it's an enumerable.
19
- class EnumMatrix < Matrix
19
+ class EnumMatrix < Matrix #:nodoc:
20
20
  include MatrixEnumMethods
21
21
 
22
22
  def row(i)
@@ -61,4 +61,4 @@ module Gecode::Util
61
61
  end
62
62
  end
63
63
  end
64
- end
64
+ end
@@ -14,15 +14,18 @@ module Gecode
14
14
  raise ArgumentError, 'Enumerable must not be empty.'
15
15
  end
16
16
 
17
- if elements.all?{ |var| var.kind_of? FreeIntVar }
17
+ if elements.all?{ |var| var.respond_to? :to_int_var }
18
+ elements.map!{ |var| var.to_int_var }
18
19
  class <<enum
19
20
  include Gecode::IntEnumMethods
20
21
  end
21
- elsif elements.all?{ |var| var.kind_of? FreeBoolVar }
22
+ elsif elements.all?{ |var| var.respond_to? :to_bool_var }
23
+ elements.map!{ |var| var.to_bool_var }
22
24
  class <<enum
23
25
  include Gecode::BoolEnumMethods
24
26
  end
25
- elsif elements.all?{ |var| var.kind_of? FreeSetVar }
27
+ elsif elements.all?{ |var| var.respond_to? :to_set_var }
28
+ elements.map!{ |var| var.to_set_var }
26
29
  class <<enum
27
30
  include Gecode::SetEnumMethods
28
31
  end
@@ -31,7 +34,7 @@ module Gecode
31
34
  include Gecode::FixnumEnumMethods
32
35
  end
33
36
  else
34
- raise TypeError, "Enumerable doesn't contain variables #{enum.inspect}."
37
+ raise TypeError, "Enumerable doesn't contain operands #{enum.inspect}."
35
38
  end
36
39
 
37
40
  enum.model = self
@@ -39,8 +42,9 @@ module Gecode
39
42
  end
40
43
  end
41
44
 
42
- # A module containing the methods needed by enumerations containing variables.
43
- module EnumMethods
45
+ # A module containing the methods needed by enumerations containing
46
+ # operands.
47
+ module EnumMethods #:nodoc:
44
48
  attr_accessor :model
45
49
  # Gets the current space of the model the array is connected to.
46
50
  def active_space
@@ -48,22 +52,23 @@ module Gecode
48
52
  end
49
53
  end
50
54
 
51
- module VariableEnumMethods
55
+ module VariableEnumMethods #:nodoc:
52
56
  include EnumMethods
53
57
 
54
- # Gets the values of all the variables in the enum.
58
+ # Gets the values of all the operands in the enum.
55
59
  def values
56
60
  map{ |var| var.value }
57
61
  end
58
62
  end
59
63
 
60
64
  # A module containing the methods needed by enumerations containing int
61
- # variables. Requires that it's included in an enumerable.
62
- module IntEnumMethods
65
+ # operands. Requires that it's included in an enumerable.
66
+ module IntEnumMethods #:nodoc:
67
+ include IntEnum::IntEnumOperand
63
68
  include VariableEnumMethods
64
69
 
65
70
  # Returns an int variable array with all the bound variables.
66
- def to_int_var_array
71
+ def bind_array
67
72
  space = @model.active_space
68
73
  unless @bound_space == space
69
74
  elements = to_a
@@ -73,7 +78,11 @@ module Gecode
73
78
  end
74
79
  return @bound_arr
75
80
  end
76
- alias_method :to_var_array, :to_int_var_array
81
+
82
+ # Returns the receiver.
83
+ def to_int_enum
84
+ self
85
+ end
77
86
 
78
87
  # Returns the smallest range that contains the domains of all integer
79
88
  # variables involved.
@@ -89,14 +98,21 @@ module Gecode
89
98
  end
90
99
  end
91
100
  end
101
+
102
+ # A dummy class that just shows what methods an int enum responds to.
103
+ class IntEnum::Dummy < Array #:nodoc:
104
+ include IntEnum::IntEnumOperand
105
+ include VariableEnumMethods
106
+ end
92
107
 
93
108
  # A module containing the methods needed by enumerations containing boolean
94
- # variables. Requires that it's included in an enumerable.
95
- module BoolEnumMethods
109
+ # operands. Requires that it's included in an enumerable.
110
+ module BoolEnumMethods #:nodoc:
111
+ include BoolEnum::BoolEnumOperand
96
112
  include VariableEnumMethods
97
113
 
98
114
  # Returns a bool variable array with all the bound variables.
99
- def to_bool_var_array
115
+ def bind_array
100
116
  space = @model.active_space
101
117
  unless @bound_space == space
102
118
  elements = to_a
@@ -106,16 +122,27 @@ module Gecode
106
122
  end
107
123
  return @bound_arr
108
124
  end
109
- alias_method :to_var_array, :to_bool_var_array
125
+
126
+ # Returns the receiver.
127
+ def to_bool_enum
128
+ self
129
+ end
130
+ end
131
+
132
+ # A dummy class that just shows what methods a bool enum responds to.
133
+ class BoolEnum::Dummy < Array #:nodoc:
134
+ include BoolEnum::BoolEnumOperand
135
+ include VariableEnumMethods
110
136
  end
111
137
 
112
138
  # A module containing the methods needed by enumerations containing set
113
- # variables. Requires that it's included in an enumerable.
114
- module SetEnumMethods
139
+ # operands. Requires that it's included in an enumerable.
140
+ module SetEnumMethods #:nodoc:
141
+ include SetEnum::SetEnumOperand
115
142
  include VariableEnumMethods
116
143
 
117
144
  # Returns a set variable array with all the bound variables.
118
- def to_set_var_array
145
+ def bind_array
119
146
  space = @model.active_space
120
147
  unless @bound_space == space
121
148
  elements = to_a
@@ -125,8 +152,12 @@ module Gecode
125
152
  end
126
153
  return @bound_arr
127
154
  end
128
- alias_method :to_var_array, :to_set_var_array
129
155
 
156
+ # Returns the receiver.
157
+ def to_set_enum
158
+ self
159
+ end
160
+
130
161
  # Returns the range of the union of the contained sets' upper bounds.
131
162
  def upper_bound_range
132
163
  inject(nil) do |range, var|
@@ -141,16 +172,34 @@ module Gecode
141
172
  end
142
173
  end
143
174
  end
175
+
176
+ # A dummy class that just shows what methods a set enum responds to.
177
+ class SetEnum::Dummy < Array #:nodoc:
178
+ include SetEnum::SetEnumOperand
179
+ include VariableEnumMethods
180
+ end
144
181
 
145
182
  # A module containing the methods needed by enumerations containing fixnums.
146
183
  # Requires that it's included in an enumerable.
147
- module FixnumEnumMethods
184
+ module FixnumEnumMethods #:nodoc:
185
+ include FixnumEnum::FixnumEnumOperand
148
186
  include EnumMethods
149
187
 
188
+ # Returns the receiver.
189
+ def to_fixnum_enum
190
+ self
191
+ end
192
+
150
193
  # Returns the smallest range that contains the domains of all integer
151
194
  # variables involved.
152
195
  def domain_range
153
196
  min..max
154
197
  end
155
198
  end
156
- end
199
+
200
+ # A dummy class that just shows what methods a fixnum enum responds to.
201
+ class FixnumEnum::Dummy < Array #:nodoc:
202
+ include FixnumEnum::FixnumEnumOperand
203
+ include VariableEnumMethods
204
+ end
205
+ end
@@ -1,5 +1,113 @@
1
1
  module Gecode
2
2
  # Model is the base class that all models must inherit from.
3
+ #
4
+ # == Formulating problems
5
+ #
6
+ # Models are used to formulate the problems that Gecode should solve.
7
+ # Below is an example of a model that formulates the problem of finding
8
+ # a solution to the following equation system.
9
+ #
10
+ # Equation system:
11
+ # x + y = z
12
+ # x = y - 3
13
+ # 0 <= x,y,z <= 9
14
+ #
15
+ # Model:
16
+ # class EquationProblem < Gecode::Model
17
+ # attr :vars
18
+ #
19
+ # def initialize
20
+ # x, y, z = @vars = int_var_array(3, 0..9)
21
+ #
22
+ # (x + y).must == z
23
+ # x.must == y - 3
24
+ #
25
+ # branch_on @vars
26
+ # end
27
+ # end
28
+ #
29
+ # A model typically consists of three main parts:
30
+ # [Variables] Variables specify how to view the problem. A solution is an
31
+ # assignment of the variables. In the example above we created
32
+ # an array of three integer variables with domains 0..9 and gave
33
+ # it the name +variables+.
34
+ #
35
+ # There are three types of variables: integer variables
36
+ # (Gecode::IntVar, can be assigned one of many
37
+ # possible integer values), boolean variables
38
+ # (Gecode::BoolVar, can be assigned either true or
39
+ # false) and set variables (Gecode::SetVar, can be
40
+ # assigned a set of integers). Variables of the different
41
+ # types are constructed using #int_var, #int_var_array,
42
+ # #int_var_matrix, #bool_var, #bool_var_array,
43
+ # #bool_var_matrix, #set_var, #set_var_array and
44
+ # #set_var_matrix .
45
+ #
46
+ # The various variables all have the functionality of Operand
47
+ # and have many properties depending on their type. For
48
+ # instance integer variables have the properties defined
49
+ # in Gecode::Int::IntOperand and
50
+ # enumerations of integer variables (such as the array
51
+ # +variables+ we used) have the properties defined in
52
+ # Gecode::IntEnum::IntEnumOperand .
53
+ #
54
+ # [Constraints] Constraints are placed on the variables to ensure that a
55
+ # valid assignment of the variables must also be a solution.
56
+ # In the example above we constrained the variables so
57
+ # that all equations were satisfied (which is exactly when
58
+ # we have found a solution).
59
+ #
60
+ # The various constraints that can be placed on the various
61
+ # kinds of operands are found in the respective
62
+ # constraint receivers. For instance, the constraints
63
+ # that can be placed on integer operands are found in
64
+ # Gecode::Int::IntConstraintReceiver and
65
+ # the constraints that can be placed on enumerations of
66
+ # integer operands are found in
67
+ # Gecode::IntEnum::IntEnumConstraintReceiver .
68
+ #
69
+ # [Branching] "branch_on variables" in the example tells Gecode that
70
+ # it should explore the search space until it has assigned
71
+ # +variables+ (or exhausted the search space). It also
72
+ # tells Gecode in what order the search space should be
73
+ # explore, which can have a big effect on the search
74
+ # performance. See #branch_on for details.
75
+ #
76
+ # == Finding solutions
77
+ #
78
+ # Solutions to a formulated problem are found are found by using
79
+ # methods such as #solve!, #solution, #each_solution . If one wants to
80
+ # find a solution that optimizes a certain quantity (i.e. maximizes a
81
+ # certain variable) then one should have a look at #maximize!,
82
+ # #minimize! and #optimize! .
83
+ #
84
+ # The first solution to the example above could for instance be found
85
+ # using
86
+ #
87
+ # puts EquationProblem.new.solve!.vars.values.join(', ')
88
+ #
89
+ # which would find the first solution to the problem, access the
90
+ # assigned values of +variables+ and print them (in order x, y, z).
91
+ #
92
+ # == Shorter ways of formulating problems
93
+ #
94
+ # Problems can also be formulated without defining a new class by
95
+ # using Gecode#solve et al.
96
+ #
97
+ # Additionally one can use "foo_is_an ..." to create an accessor of
98
+ # name foo, without having to use instance variables. The above
99
+ # problem becomes
100
+ # class EquationProblem < Gecode::Model
101
+ # def initialize
102
+ # x, y, z = vars_is_an int_var_array(3, 0..9)
103
+ #
104
+ # (x + y).must == z
105
+ # x.must == y - 3
106
+ #
107
+ # branch_on vars
108
+ # end
109
+ # end
110
+ #
3
111
  class Model
4
112
  # The largest integer allowed in the domain of an integer variable.
5
113
  MAX_INT = Gecode::Raw::IntLimits::MAX
@@ -25,7 +133,7 @@ module Gecode
25
133
  # domain is specified then the largest possible domain is used.
26
134
  def int_var(domain = LARGEST_INT_DOMAIN)
27
135
  args = domain_arguments(domain)
28
- FreeIntVar.new(self, variable_creation_space.new_int_var(*args))
136
+ IntVar.new(self, variable_creation_space.new_int_var(*args))
29
137
  end
30
138
 
31
139
  # Creates an array containing the specified number of integer variables
@@ -35,7 +143,7 @@ module Gecode
35
143
  def int_var_array(count, domain = LARGEST_INT_DOMAIN)
36
144
  args = domain_arguments(domain)
37
145
  build_var_array(count) do
38
- FreeIntVar.new(self, variable_creation_space.new_int_var(*args))
146
+ IntVar.new(self, variable_creation_space.new_int_var(*args))
39
147
  end
40
148
  end
41
149
 
@@ -46,19 +154,19 @@ module Gecode
46
154
  def int_var_matrix(row_count, col_count, domain = LARGEST_INT_DOMAIN)
47
155
  args = domain_arguments(domain)
48
156
  build_var_matrix(row_count, col_count) do
49
- FreeIntVar.new(self, variable_creation_space.new_int_var(*args))
157
+ IntVar.new(self, variable_creation_space.new_int_var(*args))
50
158
  end
51
159
  end
52
160
 
53
161
  # Creates a new boolean variable.
54
162
  def bool_var
55
- FreeBoolVar.new(self, variable_creation_space.new_bool_var)
163
+ BoolVar.new(self, variable_creation_space.new_bool_var)
56
164
  end
57
165
 
58
166
  # Creates an array containing the specified number of boolean variables.
59
167
  def bool_var_array(count)
60
168
  build_var_array(count) do
61
- FreeBoolVar.new(self, variable_creation_space.new_bool_var)
169
+ BoolVar.new(self, variable_creation_space.new_bool_var)
62
170
  end
63
171
  end
64
172
 
@@ -66,7 +174,7 @@ module Gecode
66
174
  # boolean variables.
67
175
  def bool_var_matrix(row_count, col_count)
68
176
  build_var_matrix(row_count, col_count) do
69
- FreeBoolVar.new(self, variable_creation_space.new_bool_var)
177
+ BoolVar.new(self, variable_creation_space.new_bool_var)
70
178
  end
71
179
  end
72
180
 
@@ -82,7 +190,7 @@ module Gecode
82
190
  def set_var(glb_domain = [], lub_domain = LARGEST_SET_BOUND,
83
191
  cardinality_range = nil)
84
192
  args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
85
- FreeSetVar.new(self, variable_creation_space.new_set_var(*args))
193
+ SetVar.new(self, variable_creation_space.new_set_var(*args))
86
194
  end
87
195
 
88
196
  # Creates an array containing the specified number of set variables. The
@@ -91,7 +199,7 @@ module Gecode
91
199
  cardinality_range = nil)
92
200
  args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
93
201
  build_var_array(count) do
94
- FreeSetVar.new(self, variable_creation_space.new_set_var(*args))
202
+ SetVar.new(self, variable_creation_space.new_set_var(*args))
95
203
  end
96
204
  end
97
205
 
@@ -102,7 +210,7 @@ module Gecode
102
210
  lub_domain = LARGEST_SET_BOUND, cardinality_range = nil)
103
211
  args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
104
212
  build_var_matrix(row_count, col_count) do
105
- FreeSetVar.new(self, variable_creation_space.new_set_var(*args))
213
+ SetVar.new(self, variable_creation_space.new_set_var(*args))
106
214
  end
107
215
  end
108
216
 
@@ -157,7 +265,54 @@ module Gecode
157
265
  def track_variable(variable) #:nodoc:
158
266
  (@variables ||= []) << variable
159
267
  end
160
-
268
+
269
+ # Wraps method missing to handle #foo_is_a and #foo_is_an .
270
+ #
271
+ # "<variable_name>_is_a <variable>" or "<variable_name>_is_an <variable>",
272
+ # replacing "<variable_name>" with the variable's name and
273
+ # "<variable>" with the variable, adds an instance variable and
274
+ # accessor with the specified name.
275
+ #
276
+ # The method also returns the variable given.
277
+ #
278
+ # ==== Example
279
+ #
280
+ # # Add an instance variable and accessor named "foo" that return
281
+ # # the integer variable.
282
+ # foo_is_an int_var(0..9)
283
+ #
284
+ # # Add an instance variable and accessor named "bar" that return
285
+ # # the boolean variable array.
286
+ # bar_is_a bool_var_array(2)
287
+ def method_missing(name_symbol, *args)
288
+ name = name_symbol.to_s
289
+ if name =~ /._is_an?$/
290
+ name.sub!(/_is_an?$/, '')
291
+ unless args.size == 1
292
+ raise ArgumentError, "Wrong number of argmuments (#{args.size} for 1)."
293
+ end
294
+ if respond_to? name
295
+ raise ArgumentError, "Method with name #{name} already exists."
296
+ end
297
+ if instance_variable_defined? "@#{name}"
298
+ raise ArgumentError,
299
+ "Instance variable with name @#{name} already exists."
300
+ end
301
+
302
+ # We use the meta class to avoid defining the variable in all
303
+ # other instances of the class.
304
+ eval <<-"end_eval"
305
+ @#{name} = args.first
306
+ class <<self
307
+ attr :#{name}
308
+ end
309
+ end_eval
310
+ return args.first
311
+ else
312
+ super
313
+ end
314
+ end
315
+
161
316
  protected
162
317
 
163
318
  # Gets a queue of objects that can be posted to the model's active_space
@@ -231,8 +386,8 @@ module Gecode
231
386
  def set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
232
387
  check_set_bounds(glb_domain, lub_domain)
233
388
  args = []
234
- args << Gecode::Constraints::Util.constant_set_to_int_set(glb_domain)
235
- args << Gecode::Constraints::Util.constant_set_to_int_set(lub_domain)
389
+ args << Gecode::Util.constant_set_to_int_set(glb_domain)
390
+ args << Gecode::Util.constant_set_to_int_set(lub_domain)
236
391
  card_range = to_set_cardinality_range(cardinality_range)
237
392
  if card_range.nil?
238
393
  card_range = 0..Gecode::Raw::SetLimits::CARD