gecoder-with-gecode 0.8.2-mswin32 → 0.8.3-mswin32

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 (34) hide show
  1. data/CHANGES +14 -0
  2. data/lib/gecode.dll +0 -0
  3. data/lib/gecoder/bindings/bindings.rb +104 -46
  4. data/lib/gecoder/interface/binding_changes.rb +1 -301
  5. data/lib/gecoder/interface/branch.rb +15 -11
  6. data/lib/gecoder/interface/constraints.rb +38 -0
  7. data/lib/gecoder/interface/constraints/bool/boolean.rb +56 -52
  8. data/lib/gecoder/interface/constraints/bool/channel.rb +1 -16
  9. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +13 -8
  10. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +48 -0
  11. data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
  12. data/lib/gecoder/interface/constraints/int/channel.rb +1 -13
  13. data/lib/gecoder/interface/constraints/int_enum/channel.rb +15 -35
  14. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +130 -0
  15. data/lib/gecoder/interface/constraints/set/channel.rb +54 -0
  16. data/lib/gecoder/interface/constraints/set_enum/channel.rb +37 -6
  17. data/lib/gecoder/interface/constraints/set_var_constraints.rb +1 -0
  18. data/lib/gecoder/interface/model.rb +110 -85
  19. data/lib/gecoder/interface/variables.rb +3 -21
  20. data/lib/gecoder/version.rb +1 -1
  21. data/specs/branch.rb +16 -1
  22. data/specs/constraints/bool_enum_relation.rb +6 -6
  23. data/specs/constraints/boolean.rb +31 -25
  24. data/specs/constraints/channel.rb +102 -4
  25. data/specs/constraints/extensional.rb +185 -2
  26. data/specs/constraints/reification_sugar.rb +2 -46
  27. data/specs/model.rb +85 -7
  28. data/tasks/dependencies.txt +1 -0
  29. data/vendor/rust/rust/class.rb +33 -35
  30. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +1 -1
  31. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +10 -1
  32. metadata +186 -185
  33. data/example/raw_bindings.rb +0 -44
  34. data/specs/binding_changes.rb +0 -76
@@ -35,19 +35,7 @@ module Gecode::Constraints::Int
35
35
  # set to k then the integer variable takes value i+k exactly
36
36
  # when the variable at index i in the boolean enumration is true
37
37
  # and the rest are false.
38
- def channel(bool_enum, options = {})
39
- unless bool_enum.respond_to? :to_bool_var_array
40
- raise TypeError, 'Expected an enumration of boolean variables, got ' +
41
- "#{bool_enum.class}."
42
- end
43
-
44
- # Just provide commutivity with the boolean enum channel constraint.
45
- if @params[:negate]
46
- bool_enum.must_not.channel(@params[:lhs], options)
47
- else
48
- bool_enum.must.channel(@params[:lhs], options)
49
- end
50
- end
38
+ provide_commutivity(:channel){ |rhs, _| rhs.respond_to? :to_bool_var_array }
51
39
  end
52
40
 
53
41
  # A module that gathers the classes and modules used in channel constraints
@@ -7,23 +7,20 @@ module Gecode::Constraints::IntEnum
7
7
  raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
8
8
  'is not implemented.'
9
9
  end
10
- unless enum.respond_to?(:to_int_var_array) or
11
- enum.respond_to?(:to_set_var_array)
12
- raise TypeError, "Expected int or set enum, got #{enum.class}."
10
+ unless enum.respond_to?(:to_int_var_array)
11
+ raise TypeError, "Expected int enum, got #{enum.class}."
13
12
  end
14
- if enum.respond_to? :to_set_var_array
15
- if options.has_key? :reify
16
- raise ArgumentError, 'The channel constraints does not support the ' +
17
- 'reification option.'
18
- end
19
- @params.update(Gecode::Constraints::Set::Util.decode_options(options))
20
- else
21
- @params.update(Gecode::Constraints::Util.decode_options(options))
13
+ if options.has_key? :reify
14
+ raise ArgumentError, 'The channel constraints does not support the ' +
15
+ 'reification option.'
22
16
  end
23
17
 
18
+ @params.update(Gecode::Constraints::Util.decode_options(options))
24
19
  @params.update(:rhs => enum)
25
20
  @model.add_constraint Channel::ChannelConstraint.new(@model, @params)
26
21
  end
22
+
23
+ provide_commutivity(:channel){ |rhs, _| rhs.respond_to? :to_set_var_array }
27
24
  end
28
25
 
29
26
  # A module that gathers the classes and modules used in channel constraints.
@@ -33,14 +30,12 @@ module Gecode::Constraints::IntEnum
33
30
  # enumeration of set variables. Channel constraints are used to give
34
31
  # access to multiple viewpoints when modelling.
35
32
  #
36
- # When used on two integer enumeration, the channel constraint can be
37
- # thought of as constraining the arrays to be each other's inverses. When
38
- # used with an enumeration of sets the i:th set includes the value of the
39
- # j:th integer.
33
+ # The channel constraint can be thought of as constraining the arrays to
34
+ # be each other's inverses. I.e. if the i:th value in the first enumeration
35
+ # is j, then the j:th value in the second enumeration is constrained to be
36
+ # i.
40
37
  #
41
- # Neither reification nor negation is supported. Selecting strength is only
42
- # supported when using the constraint between two integer enumerations,
43
- # it's not supported when a set enumeration is used.
38
+ # Neither reification nor negation is supported.
44
39
  #
45
40
  # == Example
46
41
  #
@@ -82,26 +77,11 @@ module Gecode::Constraints::IntEnum
82
77
  #
83
78
  # elements.must.channel positions
84
79
  #
85
- # == Example (sets)
86
- #
87
- # # +set_enum+ is constrained to channel +int_enum+.
88
- # int_enum.must.channel set_enum
89
- #
90
- # # This is another way of saying the above.
91
- # set_enum.must.channel int_enum
92
80
  class ChannelConstraint < Gecode::Constraints::Constraint
93
81
  def post
94
82
  lhs, rhs = @params.values_at(:lhs, :rhs)
95
-
96
- lhs = lhs.to_int_var_array
97
- if rhs.respond_to? :to_int_var_array
98
- # Int var array.
99
- Gecode::Raw::channel(@model.active_space, lhs, rhs.to_int_var_array,
100
- *propagation_options)
101
- else
102
- # Set var array, no propagation options.
103
- Gecode::Raw::channel(@model.active_space, lhs, rhs.to_set_var_array)
104
- end
83
+ Gecode::Raw::channel(@model.active_space, lhs.to_int_var_array,
84
+ rhs.to_int_var_array, *propagation_options)
105
85
  end
106
86
  end
107
87
  end
@@ -26,6 +26,27 @@ module Gecode::Constraints::IntEnum
26
26
  @model.add_constraint Extensional::TupleConstraint.new(@model,
27
27
  @params.update(util.decode_options(options)))
28
28
  end
29
+
30
+ # Adds a constraint that forces the enumeration to match the
31
+ # specified regular expression over the integer domain. The regular
32
+ # expression is expressed using arrays and integers. See
33
+ # IntEnum::Extensional::RegexpConstraint for more information and examples of
34
+ # such regexps.
35
+ def match(regexp, options = {})
36
+ if @params[:negate]
37
+ raise Gecode::MissingConstraintError, 'A negated regexp constraint ' +
38
+ 'is not implemented.'
39
+ end
40
+ unless options[:reify].nil?
41
+ raise ArgumentError, 'Reification is not supported by the regexp ' +
42
+ 'constraint.'
43
+ end
44
+
45
+ @params[:regexp] =
46
+ Gecode::Constraints::Util::Extensional.parse_regexp regexp
47
+ @params.update Gecode::Constraints::Util.decode_options(options)
48
+ @model.add_constraint Extensional::RegexpConstraint.new(@model, @params)
49
+ end
29
50
  end
30
51
 
31
52
  # A module that gathers the classes and modules used in extensional
@@ -60,5 +81,114 @@ module Gecode::Constraints::IntEnum
60
81
  *propagation_options)
61
82
  end
62
83
  end
84
+
85
+ # Describes a regexp constraint, which constrains the enumeration of
86
+ # integer variables to match a specified regexp in the integer
87
+ # domain. Neither negation nor reification is supported.
88
+ #
89
+ # == Regexp syntax
90
+ #
91
+ # The regular expressions are specified using arrays, integers and a
92
+ # few methods provided by Model. Arrays are used to group the
93
+ # integers in sequences that must be matched. The following array
94
+ # describes a regular expression matching a 1 followed by a 7.
95
+ #
96
+ # [1, 7]
97
+ #
98
+ # Arrays can be nested or left out when not needed. I.e. the above
99
+ # is semantically equal to
100
+ #
101
+ # [[[1], 7]]
102
+ #
103
+ # A couple of methods provided by Model are used to express patterns
104
+ # beyond mere sequences:
105
+ #
106
+ # [Model#repeat] Used for specifying patterns that include patterns
107
+ # that may be repeated a given number of times. The
108
+ # number of times to repeat a pattern can be specified
109
+ # using a lower and upper bound, but the bounds can be
110
+ # omitted to for instance allow an expression to be
111
+ # repeated any number of times.
112
+ # [Model#any] Used for specifying alternatives.
113
+ #
114
+ # Additionally Model#at_least_once and Model#at_most_once are
115
+ # provided as convenience methods.
116
+ #
117
+ # === Examples
118
+ #
119
+ # # Matches 1 followed by any number of 2s.
120
+ # [1, repeat(2)]
121
+ #
122
+ # # Semantically the same as above. It just has a bunch of
123
+ # # needless brackets thrown in.
124
+ # [[1], [repeat([2])]]
125
+ #
126
+ # # Matches 1 followed by [a 2 followed by a 3] at least two times.
127
+ # # Matches e.g. 1, 2, 3, 2, 3
128
+ # [1, repeat([2, 3], 2)]
129
+ #
130
+ # # Matches between one and two [2 followed by [at least three 1]]
131
+ # # followed by between three and four 3. Matches e.g.
132
+ # # 2, 1, 1, 1, 2, 1, 1, 1, 3, 3, 3
133
+ # [repeat([2, repeat(1, 3], 1, 2), repeat(3, 3, 4)]
134
+ #
135
+ # # Matches [1, 2 or 3] followed by 4. Matches e.g. 2, 4
136
+ # [any(1, 2, 3), 4]
137
+ #
138
+ # # Matches 0 followed by [[1 followed by 2] or [3 followed by 5]].
139
+ # # Matches e.g. 0, 1, 2 as well as 0, 3, 5
140
+ # [0, any([1, 2], [3, 5])]
141
+ #
142
+ # # Matches 0 followed by [[[1 followed by 7] at least two times]
143
+ # # or [[8, 9], at most two times]. Matches e.g.
144
+ # # 0, 1, 7, 1, 7, 1, 7 as well as 0, 8, 9
145
+ # [0, any(repeat([1, 7], 2), repeat([8, 9], 0, 2)]
146
+ #
147
+ # # Matches 0 followed by at least one 1.
148
+ # [0, at_least_once(1)]
149
+ #
150
+ # # Exactly the same as the above.
151
+ # [0, repeat(1, 1)]
152
+ #
153
+ # # Matches 0 followed by at least one [[1 followed by 7] or [3
154
+ # # followed by 2]]. Matches e.g. 0, 1, 7, 3, 2, 1, 7
155
+ # [0, at_least_once(any([1, 7], [3, 2]]
156
+ #
157
+ # # Matches 0 followed by at either [[1 followed by 7] at least once]
158
+ # # or [[3 followed by 2] at least once]. Matches e.g.
159
+ # # 0, 1, 7, 1, 7 but does _not_ match 0, 1, 7, 3, 2, 1, 7
160
+ # [0, any(at_least_once([1, 7]), at_least_once([3, 2])]
161
+ #
162
+ # # Matches 0, followed by at most one 1. Matches 0 as well as
163
+ # # 0, 1
164
+ # [0, at_most_once(1)]
165
+ #
166
+ # # Exactly the same as the above.
167
+ # [0, repeat(1, 0, 1)]
168
+ #
169
+ # == Example
170
+ #
171
+ # # Constrains the two integer variables in +numbers+ to have
172
+ # # values 1 and 7.
173
+ # numbers.must.match [1, 7]
174
+ #
175
+ # # Constrains the integer variables in +numbers+ to contain the
176
+ # # value 47 followed by 11, with all other values set to -1.
177
+ # numbers.must.match [repeat(-1), 47, 11, repeat(-1)]
178
+ #
179
+ # # Constrains exactly three of the integer variables in +numbers+ to
180
+ # # contain 47 or 11, each followed by at least two
181
+ # # variables set to -1. All other variables are constrained to
182
+ # # equal -1.
183
+ # numbers.must.match repeat([repeat(-1), any(11, 47),
184
+ # repeat(-1, 2)], 3, 3)
185
+ #
186
+ class RegexpConstraint < Gecode::Constraints::Constraint
187
+ def post
188
+ lhs, regexp = @params.values_at(:lhs, :regexp)
189
+ Gecode::Raw::extensional(@model.active_space, lhs.to_int_var_array,
190
+ regexp, *propagation_options)
191
+ end
192
+ end
63
193
  end
64
194
  end
@@ -0,0 +1,54 @@
1
+ module Gecode::Constraints::Set
2
+ class Expression
3
+ # Adds a channel constraint on the set variable with the specified enum of
4
+ # boolean variables.
5
+ def channel(bool_enum, options = {})
6
+ if @params[:negate]
7
+ raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
8
+ 'is not implemented.'
9
+ end
10
+ if options.has_key? :reify
11
+ raise ArgumentError, 'The channel constraint does not support the ' +
12
+ 'reification option.'
13
+ end
14
+ unless bool_enum.respond_to? :to_bool_var_array
15
+ raise TypeError, 'Expected an enum of bool variables, ' +
16
+ "got #{bool_enum.class}."
17
+ end
18
+
19
+ @params.update(:rhs => bool_enum)
20
+ @params.update Gecode::Constraints::Set::Util.decode_options(options)
21
+ @model.add_constraint Channel::ChannelConstraint.new(@model, @params)
22
+ end
23
+ end
24
+
25
+ # A module that gathers the classes and modules used in channel constraints
26
+ # involving one set variable and a boolean enum.
27
+ module Channel #:nodoc:
28
+ # Describes a channel constraint that "channels" a set variable and an
29
+ # enumerations of boolean variables. This constrains the set variable to
30
+ # include value i exactly when the variable at index i in the boolean
31
+ # enumeration is true.
32
+ #
33
+ # Neither reification nor negation is supported. The boolean enum and set
34
+ # can be interchanged.
35
+ #
36
+ # == Examples
37
+ #
38
+ # # Constrains the enumeration of boolean variables called +bools+ to at
39
+ # # least have the first and third variables set to true
40
+ # set.must_be.superset_of [0, 2]
41
+ # set.must.channel bools
42
+ #
43
+ # # An alternative way of writing the above.
44
+ # set.must_be.superset_of [0, 2]
45
+ # bools.must.channel set
46
+ class ChannelConstraint < Gecode::Constraints::Constraint
47
+ def post
48
+ lhs, rhs = @params.values_at(:lhs, :rhs)
49
+ Gecode::Raw::channel(@model.active_space, rhs.to_bool_var_array,
50
+ lhs.bind)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -2,16 +2,47 @@ module Gecode::Constraints::SetEnum
2
2
  class Expression
3
3
  # Posts a channel constraint on the variables in the enum with the specified
4
4
  # int enum.
5
- def channel(enum)
5
+ def channel(enum, options = {})
6
6
  unless enum.respond_to? :to_int_var_array
7
7
  raise TypeError, "Expected integer variable enum, for #{enum.class}."
8
8
  end
9
-
10
- # Just provide commutativity to the corresponding int enum constraint.
11
9
  if @params[:negate]
12
- enum.must_not.channel(@params[:lhs])
13
- else
14
- enum.must.channel(@params[:lhs])
10
+ raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
11
+ 'is not implemented.'
12
+ end
13
+ if options.has_key? :reify
14
+ raise ArgumentError, 'The channel constraints does not support the ' +
15
+ 'reification option.'
16
+ end
17
+
18
+ @params.update(Gecode::Constraints::Set::Util.decode_options(options))
19
+ @params.update(:rhs => enum)
20
+ @model.add_constraint Channel::IntChannelConstraint.new(@model, @params)
21
+ end
22
+ end
23
+
24
+ # A module that gathers the classes and modules used in channel constraints.
25
+ module Channel #:nodoc:
26
+ # Describes a channel constraint which "channels" one enumeration of
27
+ # integer variables with one enumeration of set variables. The i:th set
28
+ # in the enumeration of set variables is constrainde to includes the value
29
+ # of the j:th integer variable.
30
+ #
31
+ # Neither reification nor negation is supported.
32
+ #
33
+ # == Examples
34
+ #
35
+ # # +set_enum+ is constrained to channel +int_enum+.
36
+ # int_enum.must.channel set_enum
37
+ #
38
+ # # This is another way of saying the above.
39
+ # set_enum.must.channel int_enum
40
+ #
41
+ class IntChannelConstraint < Gecode::Constraints::Constraint
42
+ def post
43
+ lhs, rhs = @params.values_at(:lhs, :rhs)
44
+ Gecode::Raw::channel(@model.active_space, rhs.to_int_var_array,
45
+ lhs.to_set_var_array)
15
46
  end
16
47
  end
17
48
  end
@@ -75,3 +75,4 @@ require 'gecoder/interface/constraints/set/relation'
75
75
  require 'gecoder/interface/constraints/set/cardinality'
76
76
  require 'gecoder/interface/constraints/set/connection'
77
77
  require 'gecoder/interface/constraints/set/operation'
78
+ require 'gecoder/interface/constraints/set/channel'
@@ -1,117 +1,109 @@
1
1
  module Gecode
2
2
  # Model is the base class that all models must inherit from.
3
3
  class Model
4
+ # The largest integer allowed in the domain of an integer variable.
5
+ MAX_INT = Gecode::Raw::IntLimits::MAX
6
+ # The smallest integer allowed in the domain of an integer variable.
7
+ MIN_INT = Gecode::Raw::IntLimits::MIN
8
+
9
+ # The largest integer allowed in the domain of a set variable.
10
+ SET_MAX_INT = Gecode::Raw::SetLimits::MAX
11
+ # The smallest integer allowed in the domain of a set variable.
12
+ SET_MIN_INT = Gecode::Raw::SetLimits::MIN
13
+
14
+ # The largest possible domain for an integer variable.
15
+ LARGEST_INT_DOMAIN = MIN_INT..MAX_INT
16
+ # The largest possible domain, without negative integers, for an
17
+ # integer variable.
18
+ NON_NEGATIVE_INT_DOMAIN = 0..MAX_INT
19
+
20
+ # The largest possible bound for a set variable.
21
+ LARGEST_SET_BOUND = SET_MIN_INT..SET_MAX_INT
22
+
4
23
  # Creates a new integer variable with the specified domain. The domain can
5
24
  # either be a range, a single element, or an enumeration of elements. If no
6
25
  # domain is specified then the largest possible domain is used.
7
- def int_var(domain =
8
- Gecode::Raw::IntLimits::MIN..Gecode::Raw::IntLimits::MAX)
9
- enum = domain_enum(domain)
10
- index = variable_creation_space.new_int_vars(enum).first
11
- FreeIntVar.new(self, index)
26
+ def int_var(domain = LARGEST_INT_DOMAIN)
27
+ args = domain_arguments(domain)
28
+ FreeIntVar.new(self, variable_creation_space.new_int_var(*args))
12
29
  end
13
30
 
14
31
  # Creates an array containing the specified number of integer variables
15
32
  # with the specified domain. The domain can either be a range, a single
16
- # element, or an enumeration of elements.
17
- def int_var_array(count, domain)
18
- enum = domain_enum(domain)
19
- variables = []
20
- variable_creation_space.new_int_vars(enum, count).each do |index|
21
- variables << FreeIntVar.new(self, index)
33
+ # element, or an enumeration of elements. If no domain is specified then
34
+ # the largest possible domain is used.
35
+ def int_var_array(count, domain = LARGEST_INT_DOMAIN)
36
+ args = domain_arguments(domain)
37
+ build_var_array(count) do
38
+ FreeIntVar.new(self, variable_creation_space.new_int_var(*args))
22
39
  end
23
- return wrap_enum(variables)
24
40
  end
25
41
 
26
42
  # Creates a matrix containing the specified number rows and columns of
27
43
  # integer variables with the specified domain. The domain can either be a
28
- # range, a single element, or an enumeration of elements.
29
- def int_var_matrix(row_count, col_count, domain)
30
- enum = domain_enum(domain)
31
- indices = variable_creation_space.new_int_vars(enum, row_count*col_count)
32
- rows = []
33
- row_count.times do |i|
34
- rows << indices[(i*col_count)...(i.succ*col_count)].map! do |index|
35
- FreeIntVar.new(self, index)
36
- end
44
+ # range, a single element, or an enumeration of elements. If no domain
45
+ # is specified then the largest possible domain is used.
46
+ def int_var_matrix(row_count, col_count, domain = LARGEST_INT_DOMAIN)
47
+ args = domain_arguments(domain)
48
+ build_var_matrix(row_count, col_count) do
49
+ FreeIntVar.new(self, variable_creation_space.new_int_var(*args))
37
50
  end
38
- return wrap_enum(Util::EnumMatrix.rows(rows, false))
39
51
  end
40
52
 
41
53
  # Creates a new boolean variable.
42
54
  def bool_var
43
- index = variable_creation_space.new_bool_vars.first
44
- FreeBoolVar.new(self, index)
55
+ FreeBoolVar.new(self, variable_creation_space.new_bool_var)
45
56
  end
46
57
 
47
58
  # Creates an array containing the specified number of boolean variables.
48
59
  def bool_var_array(count)
49
- variables = []
50
- variable_creation_space.new_bool_vars(count).each do |index|
51
- variables << FreeBoolVar.new(self, index)
60
+ build_var_array(count) do
61
+ FreeBoolVar.new(self, variable_creation_space.new_bool_var)
52
62
  end
53
- return wrap_enum(variables)
54
63
  end
55
64
 
56
65
  # Creates a matrix containing the specified number rows and columns of
57
66
  # boolean variables.
58
67
  def bool_var_matrix(row_count, col_count)
59
- indices = variable_creation_space.new_bool_vars(row_count*col_count)
60
- rows = []
61
- row_count.times do |i|
62
- rows << indices[(i*col_count)...(i.succ*col_count)].map! do |index|
63
- FreeBoolVar.new(self, index)
64
- end
68
+ build_var_matrix(row_count, col_count) do
69
+ FreeBoolVar.new(self, variable_creation_space.new_bool_var)
65
70
  end
66
- return wrap_enum(Util::EnumMatrix.rows(rows, false))
67
71
  end
68
72
 
69
73
  # Creates a set variable with the specified domain for greatest lower bound
70
74
  # and least upper bound (specified as either a fixnum, range or enum). If
71
- # no bounds are specified then the empty set is used as greates lower bound
72
- # and the universe as least upper bound. A range for the allowed cardinality
73
- # of the set can also be specified, if none is specified, or nil is given,
74
- # then the default range (anything) will be used. If only a single Fixnum is
75
+ # no bounds are specified then the empty set is used as greatest lower
76
+ # bound and the largest possible set as least upper bound.
77
+ #
78
+ # A range for the allowed cardinality of the set can also be
79
+ # specified, if none is specified, or nil is given, then the default
80
+ # range (anything) will be used. If only a single Fixnum is
75
81
  # specified as cardinality_range then it's used as lower bound.
76
- def set_var(glb_domain = [], lub_domain =
77
- Gecode::Raw::SetLimits::MIN..Gecode::Raw::SetLimits::MAX,
82
+ def set_var(glb_domain = [], lub_domain = LARGEST_SET_BOUND,
78
83
  cardinality_range = nil)
79
- check_set_bounds(glb_domain, lub_domain)
80
-
81
- index = variable_creation_space.new_set_vars(glb_domain, lub_domain,
82
- to_set_cardinality_range(cardinality_range)).first
83
- FreeSetVar.new(self, index)
84
+ args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
85
+ FreeSetVar.new(self, variable_creation_space.new_set_var(*args))
84
86
  end
85
87
 
86
88
  # Creates an array containing the specified number of set variables. The
87
89
  # parameters beyond count are the same as for #set_var .
88
- def set_var_array(count, glb_domain, lub_domain, cardinality_range = nil)
89
- check_set_bounds(glb_domain, lub_domain)
90
-
91
- variables = []
92
- variable_creation_space.new_set_vars(glb_domain, lub_domain,
93
- to_set_cardinality_range(cardinality_range), count).each do |index|
94
- variables << FreeSetVar.new(self, index)
90
+ def set_var_array(count, glb_domain = [], lub_domain = LARGEST_SET_BOUND,
91
+ cardinality_range = nil)
92
+ args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
93
+ build_var_array(count) do
94
+ FreeSetVar.new(self, variable_creation_space.new_set_var(*args))
95
95
  end
96
- return wrap_enum(variables)
97
96
  end
98
97
 
99
98
  # Creates a matrix containing the specified number of rows and columns
100
99
  # filled with set variables. The parameters beyond row and column counts are
101
100
  # the same as for #set_var .
102
- def set_var_matrix(row_count, col_count, glb_domain, lub_domain,
103
- cardinality_range = nil)
104
- check_set_bounds(glb_domain, lub_domain)
105
-
106
- indices = variable_creation_space.new_set_vars(glb_domain, lub_domain,
107
- to_set_cardinality_range(cardinality_range), row_count*col_count)
108
- rows = []
109
- row_count.times do |i|
110
- rows << indices[(i*col_count)...(i.succ*col_count)].map! do |index|
111
- FreeSetVar.new(self, index)
112
- end
101
+ def set_var_matrix(row_count, col_count, glb_domain = [],
102
+ lub_domain = LARGEST_SET_BOUND, cardinality_range = nil)
103
+ args = set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
104
+ build_var_matrix(row_count, col_count) do
105
+ FreeSetVar.new(self, variable_creation_space.new_set_var(*args))
113
106
  end
114
- return wrap_enum(Util::EnumMatrix.rows(rows, false))
115
107
  end
116
108
 
117
109
  # Retrieves the currently used space. Calling this method is only allowed
@@ -176,20 +168,49 @@ module Gecode
176
168
 
177
169
  private
178
170
 
179
- # Returns an enumeration of the specified domain arguments, which can
180
- # either be given as a range, a single number, or an enumerable of elements.
181
- def domain_enum(domain)
171
+ # Creates an array containing the specified number of variables, all
172
+ # constructed using the provided block..
173
+ def build_var_array(count, &block)
174
+ variables = []
175
+ count.times do
176
+ variables << yield
177
+ end
178
+ return wrap_enum(variables)
179
+ end
180
+
181
+ # Creates a matrix containing the specified number rows and columns of
182
+ # variables, all constructed using the provided block.
183
+ def build_var_matrix(row_count, col_count, &block)
184
+ rows = []
185
+ row_count.times do |i|
186
+ row = []
187
+ col_count.times do |j|
188
+ row << yield
189
+ end
190
+ rows << row
191
+ end
192
+ return wrap_enum(Util::EnumMatrix.rows(rows, false))
193
+ end
194
+
195
+ # Returns the array of arguments that correspond to the specified
196
+ # domain when given to Gecode. The domain can be given as a range,
197
+ # a single number, or an enumerable of elements.
198
+ def domain_arguments(domain)
182
199
  if domain.respond_to?(:first) and domain.respond_to?(:last) and
183
200
  domain.respond_to?(:exclude_end?)
184
201
  if domain.exclude_end?
185
- return domain.first..(domain.last - 1)
202
+ return [domain.first, (domain.last - 1)]
186
203
  else
187
- return domain
204
+ return [domain.first, domain.last]
188
205
  end
189
206
  elsif domain.kind_of? Enumerable
190
- return domain
207
+ array = domain.to_a
208
+ return [Gecode::Raw::IntSet.new(array, array.size)]
209
+ elsif domain.kind_of? Fixnum
210
+ return [domain, domain]
191
211
  else
192
- return domain..domain
212
+ raise TypeError, 'The domain must be given as an instance of ' +
213
+ "Enumerable or Fixnum, but #{domain.class} was given."
193
214
  end
194
215
  end
195
216
 
@@ -204,6 +225,21 @@ module Gecode
204
225
  end
205
226
  end
206
227
 
228
+ # Converts the specified set var domain to parameters accepted by
229
+ # Gecode. The bounds can be specified as a fixnum, range or # enum.
230
+ # The parameters are returned as an array.
231
+ def set_bounds_to_parameters(glb_domain, lub_domain, cardinality_range)
232
+ check_set_bounds(glb_domain, lub_domain)
233
+ 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)
236
+ card_range = to_set_cardinality_range(cardinality_range)
237
+ if card_range.nil?
238
+ card_range = 0..Gecode::Raw::SetLimits::CARD
239
+ end
240
+ args << card_range.first << card_range.last
241
+ end
242
+
207
243
  # Checks whether the specified greatest lower bound is a subset of least
208
244
  # upper bound. Raises ArgumentError if that is not the case.
209
245
  def check_set_bounds(glb, lub)
@@ -243,15 +279,6 @@ module Gecode
243
279
  @variable_creation_space || selected_space
244
280
  end
245
281
 
246
- # Refreshes all cached variables. This should be called if the variables
247
- # in an existing space were changed.
248
- def refresh_variables
249
- return if @variables.nil?
250
- @variables.each do |variable|
251
- variable.refresh if variable.cached?
252
- end
253
- end
254
-
255
282
  # Executes any interactions with Gecode still waiting in the queue
256
283
  # (emptying the queue) in the process.
257
284
  def perform_queued_gecode_interactions
@@ -266,8 +293,6 @@ module Gecode
266
293
  # assigned directly.
267
294
  def active_space=(new_space)
268
295
  @active_space = new_space
269
- new_space.refresh
270
- refresh_variables
271
296
  end
272
297
  end
273
- end
298
+ end