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.
- data/CHANGES +15 -0
- data/README +6 -2
- data/example/equation_system.rb +15 -0
- data/example/magic_sequence.rb +7 -7
- data/example/money.rb +36 -0
- data/example/queens.rb +7 -8
- data/example/send_most_money.rb +1 -1
- data/example/square_tiling.rb +2 -2
- data/example/sudoku-set.rb +11 -12
- data/example/sudoku.rb +40 -45
- data/ext/extconf.rb +0 -0
- data/lib/gecoder/bindings.rb +42 -0
- data/lib/gecoder/bindings/bindings.rb +16 -0
- data/lib/gecoder/interface.rb +2 -1
- data/lib/gecoder/interface/branch.rb +16 -9
- data/lib/gecoder/interface/constraints.rb +410 -451
- data/lib/gecoder/interface/constraints/bool/boolean.rb +205 -213
- data/lib/gecoder/interface/constraints/bool/channel.rb +4 -5
- data/lib/gecoder/interface/constraints/bool/linear.rb +192 -21
- data/lib/gecoder/interface/constraints/bool_enum/channel.rb +43 -39
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +43 -49
- data/lib/gecoder/interface/constraints/bool_enum/relation.rb +38 -71
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +73 -22
- data/lib/gecoder/interface/constraints/bool_var_constraints.rb +140 -61
- data/lib/gecoder/interface/constraints/extensional_regexp.rb +4 -4
- data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
- data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
- data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
- data/lib/gecoder/interface/constraints/int/arithmetic.rb +131 -130
- data/lib/gecoder/interface/constraints/int/channel.rb +21 -31
- data/lib/gecoder/interface/constraints/int/domain.rb +45 -42
- data/lib/gecoder/interface/constraints/int/linear.rb +85 -239
- data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
- data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +55 -64
- data/lib/gecoder/interface/constraints/int_enum/channel.rb +35 -37
- data/lib/gecoder/interface/constraints/int_enum/count.rb +53 -78
- data/lib/gecoder/interface/constraints/int_enum/distinct.rb +36 -46
- data/lib/gecoder/interface/constraints/int_enum/element.rb +39 -57
- data/lib/gecoder/interface/constraints/int_enum/equality.rb +15 -19
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +65 -72
- data/lib/gecoder/interface/constraints/int_enum/sort.rb +42 -45
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +79 -22
- data/lib/gecoder/interface/constraints/int_var_constraints.rb +215 -44
- data/lib/gecoder/interface/constraints/reifiable_constraints.rb +14 -14
- data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
- data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
- data/lib/gecoder/interface/constraints/set/cardinality.rb +43 -53
- data/lib/gecoder/interface/constraints/set/channel.rb +26 -29
- data/lib/gecoder/interface/constraints/set/connection.rb +89 -152
- data/lib/gecoder/interface/constraints/set/domain.rb +112 -65
- data/lib/gecoder/interface/constraints/set/include.rb +36 -0
- data/lib/gecoder/interface/constraints/set/operation.rb +96 -110
- data/lib/gecoder/interface/constraints/set/relation.rb +114 -137
- data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
- data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
- data/lib/gecoder/interface/constraints/set_enum/channel.rb +23 -27
- data/lib/gecoder/interface/constraints/set_enum/distinct.rb +18 -19
- data/lib/gecoder/interface/constraints/set_enum/operation.rb +62 -53
- data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
- data/lib/gecoder/interface/constraints/set_enum_constraints.rb +73 -23
- data/lib/gecoder/interface/constraints/set_var_constraints.rb +222 -57
- data/lib/gecoder/interface/enum_matrix.rb +4 -4
- data/lib/gecoder/interface/enum_wrapper.rb +71 -22
- data/lib/gecoder/interface/model.rb +167 -12
- data/lib/gecoder/interface/model_sugar.rb +84 -0
- data/lib/gecoder/interface/search.rb +30 -18
- data/lib/gecoder/interface/variables.rb +103 -33
- data/lib/gecoder/version.rb +2 -2
- data/specs/bool_var.rb +19 -12
- data/specs/constraints/{boolean.rb → bool/boolean.rb} +103 -28
- data/specs/constraints/bool/boolean_properties.rb +51 -0
- data/specs/constraints/bool/linear.rb +213 -0
- data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
- data/specs/constraints/bool_enum/channel.rb +102 -0
- data/specs/constraints/{extensional.rb → bool_enum/extensional.rb} +32 -101
- data/specs/constraints/constraint_helper.rb +149 -179
- data/specs/constraints/constraint_receivers.rb +103 -0
- data/specs/constraints/constraints.rb +6 -63
- data/specs/constraints/fixnum_enum/element.rb +58 -0
- data/specs/constraints/fixnum_enum/operation.rb +67 -0
- data/specs/constraints/int/arithmetic.rb +149 -0
- data/specs/constraints/int/channel.rb +101 -0
- data/specs/constraints/int/domain.rb +106 -0
- data/specs/constraints/int/linear.rb +183 -0
- data/specs/constraints/int/linear_properties.rb +97 -0
- data/specs/constraints/int/relation.rb +84 -0
- data/specs/constraints/int_enum/arithmetic.rb +72 -0
- data/specs/constraints/int_enum/channel.rb +57 -0
- data/specs/constraints/int_enum/count.rb +72 -0
- data/specs/constraints/int_enum/distinct.rb +80 -0
- data/specs/constraints/int_enum/element.rb +61 -0
- data/specs/constraints/int_enum/equality.rb +29 -0
- data/specs/constraints/int_enum/extensional.rb +224 -0
- data/specs/constraints/int_enum/sort.rb +167 -0
- data/specs/constraints/operands.rb +264 -0
- data/specs/constraints/property_helper.rb +443 -0
- data/specs/constraints/reification_sugar.rb +4 -5
- data/specs/constraints/selected_set/select.rb +56 -0
- data/specs/constraints/selected_set/select_properties.rb +157 -0
- data/specs/constraints/set/cardinality.rb +58 -0
- data/specs/constraints/set/cardinality_properties.rb +46 -0
- data/specs/constraints/set/channel.rb +77 -0
- data/specs/constraints/set/connection.rb +176 -0
- data/specs/constraints/set/domain.rb +197 -0
- data/specs/constraints/set/include.rb +36 -0
- data/specs/constraints/set/operation.rb +132 -0
- data/specs/constraints/set/relation.rb +117 -0
- data/specs/constraints/set_elements/relation.rb +84 -0
- data/specs/constraints/set_enum/channel.rb +80 -0
- data/specs/constraints/set_enum/distinct.rb +59 -0
- data/specs/constraints/set_enum/operation.rb +111 -0
- data/specs/constraints/set_enum/select.rb +73 -0
- data/specs/enum_wrapper.rb +53 -3
- data/specs/int_var.rb +44 -25
- data/specs/model.rb +58 -1
- data/specs/model_sugar.rb +30 -0
- data/specs/search.rb +24 -5
- data/specs/selected_set.rb +39 -0
- data/specs/set_elements.rb +34 -0
- data/specs/set_var.rb +22 -8
- data/specs/spec_helper.rb +206 -6
- data/tasks/distribution.rake +22 -7
- data/tasks/svn.rake +3 -1
- metadata +218 -134
- data/lib/gecoder/interface/constraints/set_enum/selection.rb +0 -217
- data/specs/constraints/arithmetic.rb +0 -351
- data/specs/constraints/bool_enum_relation.rb +0 -160
- data/specs/constraints/cardinality.rb +0 -157
- data/specs/constraints/channel.rb +0 -454
- data/specs/constraints/connection.rb +0 -369
- data/specs/constraints/count.rb +0 -146
- data/specs/constraints/distinct.rb +0 -164
- data/specs/constraints/element.rb +0 -108
- data/specs/constraints/equality.rb +0 -31
- data/specs/constraints/int_domain.rb +0 -70
- data/specs/constraints/int_relation.rb +0 -82
- data/specs/constraints/linear.rb +0 -340
- data/specs/constraints/selection.rb +0 -292
- data/specs/constraints/set_domain.rb +0 -185
- data/specs/constraints/set_operation.rb +0 -285
- data/specs/constraints/set_relation.rb +0 -197
- data/specs/constraints/sort.rb +0 -179
@@ -1,12 +1,12 @@
|
|
1
|
-
module Gecode
|
1
|
+
module Gecode
|
2
2
|
# Base class for all reifiable constraints.
|
3
|
-
class ReifiableConstraint < Constraint
|
4
|
-
# Gets the reification
|
3
|
+
class ReifiableConstraint < Constraint #:nodoc:
|
4
|
+
# Gets the reification operand of the constraint, nil if none exists.
|
5
5
|
def reification_var
|
6
6
|
@params[:reif]
|
7
7
|
end
|
8
8
|
|
9
|
-
# Sets the reification
|
9
|
+
# Sets the reification operand of the constraint, nil if none should be
|
10
10
|
# used.
|
11
11
|
def reification_var=(new_var)
|
12
12
|
@params[:reif] = new_var
|
@@ -15,7 +15,7 @@ module Gecode::Constraints
|
|
15
15
|
# Produces a disjunction of two reifiable constraints, producing a new
|
16
16
|
# reifiable constraint.
|
17
17
|
def |(constraint)
|
18
|
-
|
18
|
+
with_reification_operands(constraint) do |b1, b2|
|
19
19
|
# Create the disjunction constraint.
|
20
20
|
(b1 | b2).must_be.true
|
21
21
|
end
|
@@ -24,7 +24,7 @@ module Gecode::Constraints
|
|
24
24
|
# Produces a conjunction of two reifiable constraints, producing a new
|
25
25
|
# reifiable constraint.
|
26
26
|
def &(constraint)
|
27
|
-
|
27
|
+
with_reification_operands(constraint) do |b1, b2|
|
28
28
|
# Create the conjunction constraint.
|
29
29
|
(b1 & b2).must_be.true
|
30
30
|
end
|
@@ -32,14 +32,14 @@ module Gecode::Constraints
|
|
32
32
|
|
33
33
|
private
|
34
34
|
|
35
|
-
# Yields two boolean
|
36
|
-
# self's reification
|
37
|
-
# of the specified constraint. Reuses
|
38
|
-
# otherwise creates new ones.
|
39
|
-
def
|
35
|
+
# Yields two boolean operands to the specified block. The first one
|
36
|
+
# is self's reification operand and the second one is the
|
37
|
+
# reification operand of the specified constraint. Reuses
|
38
|
+
# reification operands if possible, otherwise creates new ones.
|
39
|
+
def with_reification_operands(constraint, &block)
|
40
40
|
raise TypeError unless constraint.kind_of? ReifiableConstraint
|
41
41
|
|
42
|
-
# Set up the reification
|
42
|
+
# Set up the reification operands, using existing operands if they
|
43
43
|
# exist.
|
44
44
|
con1_holds = self.reification_var
|
45
45
|
con2_holds = constraint.reification_var
|
@@ -55,7 +55,7 @@ module Gecode::Constraints
|
|
55
55
|
end
|
56
56
|
|
57
57
|
# If called the negation of the constraint will be handled using the
|
58
|
-
# reification
|
58
|
+
# reification operand. This means that the post method (which has to be
|
59
59
|
# defined prior to calling this method) doesn't have to bother about
|
60
60
|
# negation.
|
61
61
|
def self.negate_using_reification
|
@@ -75,4 +75,4 @@ module Gecode::Constraints
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
78
|
-
end
|
78
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Gecode::SelectedSet
|
2
|
+
class SelectedSetOperand
|
3
|
+
# Produces a SetOperand representing the selected sets' union.
|
4
|
+
#
|
5
|
+
# ==== Examples
|
6
|
+
#
|
7
|
+
# # The union of all sets selected by +set_enum[set]+.
|
8
|
+
# set_enum[set].union
|
9
|
+
def union
|
10
|
+
Select::SelectedSetUnionOperand.new(model, self)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Produces a SetOperand representing the selected sets' intersection.
|
14
|
+
# The option :with can be used to enumerate the elements in the
|
15
|
+
# universe.
|
16
|
+
#
|
17
|
+
# ==== Examples
|
18
|
+
#
|
19
|
+
# # The intersection of all sets selected by +set_enum[set]+.
|
20
|
+
# set_enum[set].intersection
|
21
|
+
#
|
22
|
+
# # The same intersection as above, but with [3,5,7] as universe.
|
23
|
+
# set_enum[set].intersection(:with => [3,5,7])
|
24
|
+
def intersection(options = {})
|
25
|
+
universe = nil
|
26
|
+
unless options.empty?
|
27
|
+
unless options.size == 1 and options.has_key?(:with)
|
28
|
+
raise ArgumentError, "Expected option key :with, got #{options.keys}."
|
29
|
+
else
|
30
|
+
universe = options[:with]
|
31
|
+
unless universe.kind_of?(Enumerable) and
|
32
|
+
universe.all?{ |element| element.kind_of? Fixnum }
|
33
|
+
raise TypeError, "Expected the universe to be specified as " +
|
34
|
+
"an enumeration of fixnum, got #{universe.class}."
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Select::SelectedSetIntersectionOperand.new(model, self, universe)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class SelectedSetConstraintReceiver
|
44
|
+
# Constrains the selected sets to be pairwise disjoint.
|
45
|
+
#
|
46
|
+
# ==== Examples
|
47
|
+
#
|
48
|
+
# # Constrains all sets selected by +set_enum[set]+ to be pairwise
|
49
|
+
# # disjoint.
|
50
|
+
# set_enum[set].must_be.disjoint
|
51
|
+
def disjoint(options = {})
|
52
|
+
if @params[:negate]
|
53
|
+
raise Gecode::MissingConstraintError, 'A negated disjoint constraint ' +
|
54
|
+
'is not implemented.'
|
55
|
+
end
|
56
|
+
if options.has_key? :reify
|
57
|
+
raise ArgumentError, 'The disjoint constraint does not support the ' +
|
58
|
+
'reification option.'
|
59
|
+
end
|
60
|
+
|
61
|
+
@params.update Gecode::Set::Util.decode_options(options)
|
62
|
+
@model.add_constraint Select::DisjointConstraint.new(@model, @params)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
module Select #:nodoc:
|
67
|
+
class SelectedSetUnionOperand < Gecode::Set::ShortCircuitEqualityOperand #:nodoc:
|
68
|
+
def initialize(model, selected_set)
|
69
|
+
super model
|
70
|
+
@selected_set = selected_set
|
71
|
+
end
|
72
|
+
|
73
|
+
def constrain_equal(set_operand, constrain, propagation_options)
|
74
|
+
enum, indices = @selected_set.to_selected_set
|
75
|
+
if constrain
|
76
|
+
set_operand.must_be.subset_of enum.upper_bound_range
|
77
|
+
end
|
78
|
+
|
79
|
+
Gecode::Raw::selectUnion(@model.active_space,
|
80
|
+
enum.to_set_enum.bind_array, indices.to_set_var.bind,
|
81
|
+
set_operand.to_set_var.bind)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class SelectedSetIntersectionOperand < Gecode::Set::ShortCircuitEqualityOperand #:nodoc:
|
86
|
+
def initialize(model, selected_set, universe)
|
87
|
+
super model
|
88
|
+
@selected_set = selected_set
|
89
|
+
@universe = universe
|
90
|
+
end
|
91
|
+
|
92
|
+
def constrain_equal(set_operand, constrain, propagation_options)
|
93
|
+
enum, indices = @selected_set.to_selected_set
|
94
|
+
universe = @universe
|
95
|
+
|
96
|
+
# We can't do any useful constraining here since the empty intersection
|
97
|
+
# is the universe.
|
98
|
+
|
99
|
+
if universe.nil?
|
100
|
+
Gecode::Raw::selectInter(@model.active_space,
|
101
|
+
enum.to_set_enum.bind_array, indices.to_set_var.bind,
|
102
|
+
set_operand.to_set_var.bind)
|
103
|
+
else
|
104
|
+
Gecode::Raw::selectInterIn(@model.active_space,
|
105
|
+
enum.to_set_enum.bind_array, indices.to_set_var.bind,
|
106
|
+
set_operand.to_set_var.bind,
|
107
|
+
Gecode::Util.constant_set_to_int_set(universe))
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class DisjointConstraint < Gecode::Constraint #:nodoc:
|
113
|
+
def post
|
114
|
+
enum, indices = @params[:lhs].to_selected_set
|
115
|
+
Gecode::Raw.selectDisjoint(@model.active_space,
|
116
|
+
enum.to_set_enum.bind_array, indices.to_set_var.bind)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# A module containing constraints that have set_enum[set] as left hand
|
2
|
+
# side.
|
3
|
+
module Gecode::SelectedSet #:nodoc:
|
4
|
+
# A SelectedSetOperand is an uncommon operand that results from calling
|
5
|
+
# SetEnumOperand#[] with a SetOperand. It facilitates placing the
|
6
|
+
# constraints defined in SelectedSetConstraintReceiver
|
7
|
+
#
|
8
|
+
# ==== Examples
|
9
|
+
#
|
10
|
+
# Producing a SelectedSetOperand from +set_enum+ and +set_operand+:
|
11
|
+
#
|
12
|
+
# set_enum[set_operand]
|
13
|
+
#
|
14
|
+
class SelectedSetOperand
|
15
|
+
include Gecode::Operand
|
16
|
+
|
17
|
+
# Constructs a new selected set operand from +set_enum+ and +set+.
|
18
|
+
def initialize(set_enum, set) #:nodoc:
|
19
|
+
unless set_enum.respond_to? :to_set_enum
|
20
|
+
raise TypeError, "Expected set enum operand, got #{set_enum.class}."
|
21
|
+
end
|
22
|
+
unless set.respond_to? :to_set_var
|
23
|
+
raise TypeError, "Expected set operand, got #{set.class}."
|
24
|
+
end
|
25
|
+
|
26
|
+
@set_enum = set_enum
|
27
|
+
@set = set
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the set enum and set that make up the selected set
|
31
|
+
# operand.
|
32
|
+
def to_selected_set #:nodoc:
|
33
|
+
return @set_enum, @set
|
34
|
+
end
|
35
|
+
|
36
|
+
def model #:nodoc:
|
37
|
+
@set_enum.model
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def construct_receiver(params)
|
43
|
+
SelectedSetConstraintReceiver.new(model, params)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# SelectedSetConstraintReceiver contains all constraints that can be
|
48
|
+
# placed on a SelectedSetOperand.
|
49
|
+
#
|
50
|
+
# Constraints are placed by calling SelectedSetOperand#must (or any other
|
51
|
+
# of the variations defined in Operand), which produces a
|
52
|
+
# SelectedSetConstraintReceiver from which the desired constraint can
|
53
|
+
# be used.
|
54
|
+
#
|
55
|
+
# ==== Examples
|
56
|
+
#
|
57
|
+
# Constrains the sets in +set_enum+ that are selected by +set_operand+ to be
|
58
|
+
# disjoint. This uses SetEnumOperand#[] and
|
59
|
+
# SelectedSetConstraintReceiver#disjoint.
|
60
|
+
#
|
61
|
+
# set_enum[set_operand].must_be.disjoint
|
62
|
+
#
|
63
|
+
class SelectedSetConstraintReceiver < Gecode::ConstraintReceiver
|
64
|
+
# Raises TypeError unless the left hand side is a selected set operand.
|
65
|
+
def initialize(model, params) #:nodoc:
|
66
|
+
super
|
67
|
+
|
68
|
+
unless params[:lhs].respond_to? :to_selected_set
|
69
|
+
raise TypeError, 'Must have selected set operand as left hand side.'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
require 'gecoder/interface/constraints/selected_set/select'
|
@@ -1,75 +1,65 @@
|
|
1
|
-
module Gecode
|
2
|
-
|
3
|
-
#
|
1
|
+
module Gecode::Set
|
2
|
+
module SetOperand
|
3
|
+
# Produces an IntOperand representing the size of the set.
|
4
|
+
#
|
5
|
+
# ==== Examples
|
6
|
+
#
|
7
|
+
# # The size of +set+.
|
8
|
+
# set.size
|
4
9
|
def size
|
5
|
-
|
6
|
-
Gecode::Constraints::Set::Cardinality::SizeExpressionStub.new(
|
7
|
-
@model, params)
|
10
|
+
Cardinality::SetSizeOperand.new(@model, self)
|
8
11
|
end
|
9
12
|
end
|
10
|
-
end
|
11
13
|
|
12
|
-
module Gecode::Constraints::Set
|
13
14
|
# A module that gathers the classes and modules used in cardinality
|
14
15
|
# constraints.
|
15
16
|
module Cardinality #:nodoc:
|
16
17
|
# Describes a cardinality constraint specifically for ranges. This is just
|
17
18
|
# a special case which is used instead of the more general composite
|
18
19
|
# constraint when the target cardinality is a range.
|
19
|
-
class CardinalityConstraint < Gecode::
|
20
|
+
class CardinalityConstraint < Gecode::Constraint #:nodoc:
|
20
21
|
def post
|
21
22
|
var, range = @params.values_at(:lhs, :range)
|
22
|
-
Gecode::Raw::cardinality(@model.active_space, var.bind,
|
23
|
-
range.last)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# A custom composite stub to change the composite expression used.
|
28
|
-
class CompositeStub < Gecode::Constraints::CompositeStub #:nodoc:
|
29
|
-
def initialize(model, params)
|
30
|
-
super(Expression, model, params)
|
23
|
+
Gecode::Raw::cardinality(@model.active_space, var.to_set_var.bind,
|
24
|
+
range.first, range.last)
|
31
25
|
end
|
32
26
|
end
|
33
27
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@params.update(:range => range)
|
39
|
-
@model.add_constraint CardinalityConstraint.new(@model, @params)
|
40
|
-
else
|
41
|
-
super(range)
|
42
|
-
end
|
28
|
+
class SetSizeOperand < Gecode::Int::ShortCircuitEqualityOperand #:nodoc:
|
29
|
+
def initialize(model, set_op)
|
30
|
+
super model
|
31
|
+
@set = set_op
|
43
32
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
# the cardianlity (size) of a set.
|
48
|
-
#
|
49
|
-
# == Example
|
50
|
-
#
|
51
|
-
# # The size of +set+ must be within 1..17
|
52
|
-
# set.size.must_be.in 1..17
|
53
|
-
#
|
54
|
-
# # The size must equal the integer variable +size+.
|
55
|
-
# set.size.must == size
|
56
|
-
#
|
57
|
-
# # The size must not be larger than 17
|
58
|
-
# set.size.must_not > 17
|
59
|
-
#
|
60
|
-
# # We reify the above with a boolean variable called +is_not_large+ and
|
61
|
-
# # select the strength +domain+.
|
62
|
-
# set.size.must_not_be.larger_than(17, :reify => is_not_large,
|
63
|
-
# :strength => :domain)
|
64
|
-
class SizeExpressionStub < CompositeStub
|
65
|
-
def constrain_equal(variable, params, constrain)
|
66
|
-
lhs = @params[:lhs]
|
33
|
+
|
34
|
+
def constrain_equal(int_operand, constrain, propagation_options)
|
35
|
+
set = @set.to_set_var
|
67
36
|
if constrain
|
68
|
-
|
37
|
+
int_operand.must_be.in set.lower_bound.size..set.upper_bound.size
|
69
38
|
end
|
70
39
|
|
71
|
-
Gecode::Raw::cardinality(@model.active_space,
|
40
|
+
Gecode::Raw::cardinality(@model.active_space, set.bind,
|
41
|
+
int_operand.to_int_var.bind)
|
42
|
+
end
|
43
|
+
|
44
|
+
alias_method :pre_cardinality_construct_receiver, :construct_receiver
|
45
|
+
def construct_receiver(params)
|
46
|
+
receiver = pre_cardinality_construct_receiver(params)
|
47
|
+
set = @set
|
48
|
+
receiver.instance_eval{ @set = set }
|
49
|
+
class <<receiver
|
50
|
+
alias_method :in_without_short_circuit, :in
|
51
|
+
def in(range, options = {})
|
52
|
+
if range.kind_of?(Range) and !@params[:negate] and
|
53
|
+
!options.has_key?(:reify)
|
54
|
+
@params.update(:lhs => @set, :range => range)
|
55
|
+
@model.add_constraint CardinalityConstraint.new(@model, @params)
|
56
|
+
else
|
57
|
+
in_without_short_circuit(range, options)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
return receiver
|
72
62
|
end
|
73
63
|
end
|
74
64
|
end
|
75
|
-
end
|
65
|
+
end
|
@@ -1,7 +1,22 @@
|
|
1
|
-
module Gecode::
|
2
|
-
class
|
3
|
-
#
|
4
|
-
#
|
1
|
+
module Gecode::Set
|
2
|
+
class SetConstraintReceiver
|
3
|
+
# Constrains this set to channel +bool_enum+. The set is constrained
|
4
|
+
# to include value i exactly when the operand at index i in the
|
5
|
+
# boolean enumeration is true.
|
6
|
+
#
|
7
|
+
# Neither reification nor negation is supported. The boolean enum and set
|
8
|
+
# can be interchanged.
|
9
|
+
#
|
10
|
+
# ==== Examples
|
11
|
+
#
|
12
|
+
# # Constrains the enumeration of boolean operands called +bools+ to at
|
13
|
+
# # least have the first and third operands set to true
|
14
|
+
# set.must_be.superset_of [0, 2]
|
15
|
+
# set.must.channel bools
|
16
|
+
#
|
17
|
+
# # An alternative way of writing the above.
|
18
|
+
# set.must_be.superset_of [0, 2]
|
19
|
+
# bools.must.channel set
|
5
20
|
def channel(bool_enum, options = {})
|
6
21
|
if @params[:negate]
|
7
22
|
raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
|
@@ -11,43 +26,25 @@ module Gecode::Constraints::Set
|
|
11
26
|
raise ArgumentError, 'The channel constraint does not support the ' +
|
12
27
|
'reification option.'
|
13
28
|
end
|
14
|
-
unless bool_enum.respond_to? :
|
15
|
-
raise TypeError, 'Expected an enum of bool
|
29
|
+
unless bool_enum.respond_to? :to_bool_enum
|
30
|
+
raise TypeError, 'Expected an enum of bool operands, ' +
|
16
31
|
"got #{bool_enum.class}."
|
17
32
|
end
|
18
33
|
|
19
34
|
@params.update(:rhs => bool_enum)
|
20
|
-
@params.update Gecode::
|
35
|
+
@params.update Gecode::Set::Util.decode_options(options)
|
21
36
|
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
22
37
|
end
|
23
38
|
end
|
24
39
|
|
25
40
|
# A module that gathers the classes and modules used in channel constraints
|
26
|
-
# involving one set
|
41
|
+
# involving one set operand and a boolean enum.
|
27
42
|
module Channel #:nodoc:
|
28
|
-
|
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
|
43
|
+
class ChannelConstraint < Gecode::Constraint #:nodoc:
|
47
44
|
def post
|
48
45
|
lhs, rhs = @params.values_at(:lhs, :rhs)
|
49
|
-
Gecode::Raw::channel(@model.active_space, rhs.
|
50
|
-
lhs.bind)
|
46
|
+
Gecode::Raw::channel(@model.active_space, rhs.to_bool_enum.bind_array,
|
47
|
+
lhs.to_set_var.bind)
|
51
48
|
end
|
52
49
|
end
|
53
50
|
end
|