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

Sign up to get free protection for your applications and to get access to all the features.
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