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
@@ -0,0 +1,79 @@
|
|
1
|
+
module Gecode::SetEnum
|
2
|
+
module SetEnumOperand
|
3
|
+
# This adds the adder for the methods in the modules including it. The
|
4
|
+
# reason for doing it so indirect is that the first #[] won't be defined
|
5
|
+
# before the module that this is mixed into is mixed into an enum.
|
6
|
+
def self.included(mod) #:nodoc:
|
7
|
+
mod.module_eval do
|
8
|
+
# Now we enter the module SetEnumOperands is mixed into.
|
9
|
+
class << self
|
10
|
+
alias_method :pre_selection_included, :included
|
11
|
+
def included(mod) #:nodoc:
|
12
|
+
mod.module_eval do
|
13
|
+
# Now we enter the module that the module possibly defining #[]
|
14
|
+
# is mixed into.
|
15
|
+
if instance_methods.include?('[]') and
|
16
|
+
not instance_methods.include?('pre_selection_access')
|
17
|
+
alias_method :pre_selection_access, :[]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Produces a SetOperand representing the i:th set
|
21
|
+
# operand in the enumeration, where i is the value of the
|
22
|
+
# int operand used as index.
|
23
|
+
#
|
24
|
+
# A set can also be used as index, in which case a
|
25
|
+
# SelectedSetOperand is produced.
|
26
|
+
#
|
27
|
+
# ==== Examples
|
28
|
+
#
|
29
|
+
# # The set operand at the +x+:th position in +set_enum+,
|
30
|
+
# # where +x+ is a int operand.
|
31
|
+
# set_enum[x]
|
32
|
+
#
|
33
|
+
# # The SelectedSetOperand representing sets at positions
|
34
|
+
# # included in the value of +set+ in +set_enum+,
|
35
|
+
# set_enum[set]
|
36
|
+
#
|
37
|
+
def [](*vars)
|
38
|
+
# Hook in an element constraint if a operand is used for array
|
39
|
+
# access.
|
40
|
+
if vars.first.respond_to? :to_int_var
|
41
|
+
Select::SelectSetOperand.new(
|
42
|
+
model, self, vars.first)
|
43
|
+
elsif vars.first.respond_to? :to_set_var
|
44
|
+
Gecode::SelectedSet::SelectedSetOperand.new(
|
45
|
+
self, vars.first)
|
46
|
+
else
|
47
|
+
if respond_to? :pre_selection_access
|
48
|
+
pre_selection_access(*vars)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
pre_selection_included(mod)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module Select #:nodoc:
|
61
|
+
class SelectSetOperand < Gecode::Set::ShortCircuitEqualityOperand #:nodoc:
|
62
|
+
def initialize(model, enum_op, position_int_op)
|
63
|
+
super model
|
64
|
+
@enum = enum_op
|
65
|
+
@position = position_int_op
|
66
|
+
end
|
67
|
+
|
68
|
+
def constrain_equal(set_operand, constrain, propagation_options)
|
69
|
+
enum = @enum.to_set_enum
|
70
|
+
if constrain
|
71
|
+
set_operand.must_be.subset_of enum.upper_bound_range
|
72
|
+
end
|
73
|
+
|
74
|
+
Gecode::Raw::selectSet(@model.active_space, enum.bind_array,
|
75
|
+
@position.to_int_var.bind, set_operand.to_set_var.bind)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -1,28 +1,78 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# A module containing constraints that have enumerations of set operands as
|
2
|
+
# left hand side.
|
3
|
+
module Gecode::SetEnum #:nodoc:
|
4
|
+
# A SetEnumOperand is a enumeration of SetOperand on which the
|
5
|
+
# constraints defined in SetEnumConstraintReceiver can be placed.
|
6
|
+
#
|
7
|
+
# Enumerations of set operands can be created either by using
|
8
|
+
# Gecode::Model#set_var_array and Gecode::Model#set_var_matrix, or
|
9
|
+
# by wrapping an existing enumeration containing SetOperand using
|
10
|
+
# Gecode::Model#wrap_enum. The enumerations, no matter how they were
|
11
|
+
# created, all respond to the properties defined by SetEnumOperand.
|
12
|
+
#
|
13
|
+
# ==== Examples
|
14
|
+
#
|
15
|
+
# Produces an array of five set operands, with greatest lower bound
|
16
|
+
# {0} and least upper bound {0, 1, 2}, inside a problem formulation
|
17
|
+
# using Gecode::Model#set_var_array:
|
18
|
+
#
|
19
|
+
# set_enum = set_var_array(5, 0, 1..2)
|
20
|
+
#
|
21
|
+
# Uses Gecode::Model#wrap_enum inside a problem formulation to create
|
22
|
+
# a SetEnumOperand from an existing enumeration containing the
|
23
|
+
# set operands +set_operand1+ and +set_operand2+:
|
24
|
+
#
|
25
|
+
# set_enum = wrap_enum([set_operand1, set_operand2])
|
26
|
+
#
|
27
|
+
#--
|
28
|
+
# Classes that mix in SetEnumOperand must define #model and
|
29
|
+
# #to_set_enum .
|
30
|
+
module SetEnumOperand
|
31
|
+
include Gecode::Operand
|
32
|
+
|
33
|
+
def method_missing(method, *args) #:nodoc:
|
34
|
+
if Gecode::SetEnum::Dummy.instance_methods.include? method.to_s
|
35
|
+
# Delegate to the set enum.
|
36
|
+
to_set_enum.method(method).call(*args)
|
37
|
+
else
|
38
|
+
super
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
5
42
|
private
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
params.update(:lhs => self)
|
10
|
-
Constraints::SetEnum::Expression.new(@model, params)
|
43
|
+
|
44
|
+
def construct_receiver(params)
|
45
|
+
Gecode::SetEnum::SetEnumConstraintReceiver.new(@model, params)
|
11
46
|
end
|
12
47
|
end
|
13
|
-
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
48
|
+
|
49
|
+
# SetEnumConstraintReceiver contains all constraints that can be
|
50
|
+
# placed on a SetEnumOperand.
|
51
|
+
#
|
52
|
+
# Constraints are placed by calling SetEnumOperand#must (or any other
|
53
|
+
# of the variations defined in Operand), which produces a
|
54
|
+
# SetEnumConstraintReceiver from which the desired constraint can be used.
|
55
|
+
#
|
56
|
+
# ==== Examples
|
57
|
+
#
|
58
|
+
# Constrains +set_enum+ to channel +int_enum+ by using
|
59
|
+
# SetEnumConstraintReceiver#channel:
|
60
|
+
#
|
61
|
+
# set_enum.must.channel set_enum
|
62
|
+
#
|
63
|
+
# Constrains each pair of set operands in +set_enum+ to at most share
|
64
|
+
# one element. Also constrains each set to have size 17. Uses
|
65
|
+
# SetEnumConstraintReceiver#at_most_share_one_element.
|
66
|
+
#
|
67
|
+
# set_enum.must.at_most_share_one_element(:size => 17)
|
68
|
+
#
|
69
|
+
class SetEnumConstraintReceiver < Gecode::ConstraintReceiver
|
70
|
+
# Raises TypeError unless the left hand side is a set enum operand.
|
71
|
+
def initialize(model, params) #:nodoc:
|
72
|
+
super
|
73
|
+
|
74
|
+
unless params[:lhs].respond_to? :to_set_enum
|
75
|
+
raise TypeError, 'Must have set enum operand as left hand side.'
|
26
76
|
end
|
27
77
|
end
|
28
78
|
end
|
@@ -30,5 +80,5 @@ end
|
|
30
80
|
|
31
81
|
require 'gecoder/interface/constraints/set_enum/channel'
|
32
82
|
require 'gecoder/interface/constraints/set_enum/distinct'
|
33
|
-
require 'gecoder/interface/constraints/set_enum/
|
83
|
+
require 'gecoder/interface/constraints/set_enum/select'
|
34
84
|
require 'gecoder/interface/constraints/set_enum/operation'
|
@@ -1,71 +1,235 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# A module containing constraints that have set operands as left hand side
|
2
|
+
# (but not enumerations).
|
3
|
+
module Gecode::Set #:nodoc:
|
4
|
+
# A SetOperand is a combination of operands on which the
|
5
|
+
# constraints defined in SetConstraintReceiver can be placed.
|
6
|
+
#
|
7
|
+
# Set operands can be created either by using Gecode::Model#set_var et
|
8
|
+
# al, or by using properties that produce set operands. The operands,
|
9
|
+
# no matter how they were created, all respond to the properties
|
10
|
+
# defined by SetOperand.
|
11
|
+
#
|
12
|
+
# ==== Examples
|
13
|
+
#
|
14
|
+
# Produces a single set operand (more specifically a SetVar), with
|
15
|
+
# greatest lower bound {0} and least upper bound {0, 1, 2}, inside a
|
16
|
+
# problem formulation, using Gecode::Model#set_var:
|
17
|
+
#
|
18
|
+
# set_operand = set_var(0, 0..2)
|
19
|
+
#
|
20
|
+
# Uses the SetOperand#union property to produce a new set operand
|
21
|
+
# representing the union between +set_operand1+ and +set_operand2+:
|
22
|
+
#
|
23
|
+
# new_set_operand = set_operand1.union(set_operand2)
|
24
|
+
#
|
25
|
+
# Uses the SetEnumOperand#union property to produce a new set operand
|
26
|
+
# representing the union of the set operands in the enumeration
|
27
|
+
# +set_enum+:
|
28
|
+
#
|
29
|
+
# new_set_operand = set_enum.union
|
30
|
+
#
|
31
|
+
# Uses the SetEnumOperand#[] property to produce a new set operand
|
32
|
+
# representing the set operand at the index decided by
|
33
|
+
# +int_operand+ (which can change during search) in the enumeration
|
34
|
+
# +set_enum+:
|
35
|
+
#
|
36
|
+
# new_set_operand = set_enum[int_operand]
|
37
|
+
#
|
38
|
+
#--
|
39
|
+
# Classes that mix in SetOperand must define #model and #to_set_var .
|
40
|
+
module SetOperand
|
41
|
+
include Gecode::Operand
|
42
|
+
|
43
|
+
def method_missing(method, *args) #:nodoc:
|
44
|
+
if Gecode::SetVar.instance_methods.include? method.to_s
|
45
|
+
# Delegate to the set var.
|
46
|
+
to_set_var.method(method).call(*args)
|
47
|
+
else
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
5
52
|
private
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
params.update(:lhs => self)
|
10
|
-
Constraints::Set::Expression.new(@model, params)
|
53
|
+
|
54
|
+
def construct_receiver(params)
|
55
|
+
SetConstraintReceiver.new(model, params)
|
11
56
|
end
|
12
57
|
end
|
13
|
-
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
58
|
+
|
59
|
+
# An operand that short circuits set equality.
|
60
|
+
class ShortCircuitEqualityOperand #:nodoc:
|
61
|
+
include Gecode::Set::SetOperand
|
62
|
+
attr :model
|
63
|
+
|
64
|
+
def initialize(model)
|
65
|
+
@model = model
|
19
66
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
67
|
+
|
68
|
+
def construct_receiver(params)
|
69
|
+
params.update(:lhs => self)
|
70
|
+
receiver = SetConstraintReceiver.new(@model, params)
|
71
|
+
op = self
|
72
|
+
receiver.instance_eval{ @short_circuit = op }
|
73
|
+
class <<receiver
|
74
|
+
alias_method :equality_without_short_circuit, :==
|
75
|
+
def ==(operand, options = {})
|
76
|
+
if !@params[:negate] and !options.has_key?(:reify) and
|
77
|
+
operand.respond_to? :to_set_var
|
78
|
+
# Short circuit the constraint.
|
79
|
+
@params.update Gecode::Util.decode_options(options)
|
80
|
+
@model.add_constraint(Gecode::BlockConstraint.new(
|
81
|
+
@model, @params) do
|
82
|
+
@short_circuit.constrain_equal(operand, false,
|
83
|
+
@params.values_at(:strength, :kind))
|
84
|
+
end)
|
85
|
+
else
|
86
|
+
equality_without_short_circuit(operand, options)
|
87
|
+
end
|
28
88
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
89
|
+
alias_comparison_methods
|
90
|
+
end
|
91
|
+
|
92
|
+
return receiver
|
93
|
+
end
|
94
|
+
|
95
|
+
def to_set_var
|
96
|
+
variable = model.set_var
|
97
|
+
options =
|
98
|
+
Gecode::Set::Util.decode_options(
|
99
|
+
{}).values_at(:strength, :kind)
|
100
|
+
model.add_interaction do
|
101
|
+
constrain_equal(variable, true, options)
|
102
|
+
end
|
103
|
+
return variable
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Constrains this operand to equal +set_operand+ using the
|
109
|
+
# specified +propagation_options+. If +constrain_domain+ is true
|
110
|
+
# then the method should also attempt to constrain the bounds of the
|
111
|
+
# domain of +set_operand+.
|
112
|
+
def constrain_equal(set_operand, constrain_domain, propagation_options)
|
113
|
+
raise NotImplementedError, 'Abstract method has not been implemented.'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# An operand that short circuits set non-negated and non-reified versions
|
118
|
+
# of the relation constraints.
|
119
|
+
class ShortCircuitRelationsOperand #:nodoc:
|
120
|
+
include Gecode::Set::SetOperand
|
121
|
+
attr :model
|
122
|
+
|
123
|
+
def initialize(model)
|
124
|
+
@model = model
|
125
|
+
end
|
126
|
+
|
127
|
+
def construct_receiver(params)
|
128
|
+
params.update(:lhs => self)
|
129
|
+
receiver = SetConstraintReceiver.new(@model, params)
|
130
|
+
op = self
|
131
|
+
receiver.instance_eval{ @short_circuit = op }
|
132
|
+
class <<receiver
|
133
|
+
Gecode::Util::SET_RELATION_TYPES.keys.each do |comp|
|
134
|
+
eval <<-end_code
|
135
|
+
alias_method :alias_#{comp.to_i}_without_short_circuit, :#{comp}
|
136
|
+
def #{comp}(operand, options = {})
|
137
|
+
if !@params[:negate] && !options.has_key?(:reify) &&
|
138
|
+
(operand.respond_to?(:to_set_var) or
|
139
|
+
Gecode::Util::constant_set?(operand))
|
140
|
+
# Short circuit the constraint.
|
141
|
+
@params.update Gecode::Set::Util.decode_options(options)
|
142
|
+
@model.add_constraint(
|
143
|
+
@short_circuit.relation_constraint(
|
144
|
+
:#{comp}, operand, @params))
|
145
|
+
else
|
146
|
+
alias_#{comp.to_i}_without_short_circuit(operand, options)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end_code
|
32
150
|
end
|
33
|
-
|
34
|
-
Gecode::Constraints::Util.decode_options(options)
|
151
|
+
alias_comparison_methods
|
35
152
|
end
|
153
|
+
|
154
|
+
return receiver
|
155
|
+
end
|
156
|
+
|
157
|
+
def to_set_var
|
158
|
+
variable = model.set_var
|
159
|
+
params = {:lhs => self}
|
160
|
+
params.update Gecode::Set::Util.decode_options({})
|
161
|
+
model.add_constraint relation_constraint(:==, variable, params)
|
162
|
+
return variable
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns a constraint that constrains this operand to have relation
|
166
|
+
# +relation+ to +set_operand_or_constant_set+, which is either a set
|
167
|
+
# operand or a constant set, given the specified hash +params+ of
|
168
|
+
# parameters. The constraints are never negated nor reified.
|
169
|
+
def relation_constraint(relation, set_operand_or_constant_set, params)
|
170
|
+
raise NotImplementedError, 'Abstract method has not been implemented.'
|
36
171
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
172
|
+
end
|
173
|
+
|
174
|
+
# SetConstraintReceiver contains all constraints that can be
|
175
|
+
# placed on a SetOperand.
|
176
|
+
#
|
177
|
+
# Constraints are placed by calling SetOperand#must (or any other
|
178
|
+
# of the variations defined in Operand), which produces a
|
179
|
+
# SetConstraintReceiver from which the desired constraint can be used.
|
180
|
+
#
|
181
|
+
# Most constraint accept :reify option. See ConstraintReceiver for
|
182
|
+
# more information.
|
183
|
+
#
|
184
|
+
# ==== Examples
|
185
|
+
#
|
186
|
+
# Constrains +set_operand+ to be a subset of {0, 1, 2} using
|
187
|
+
# an alias of SetConstraintReceiver#subset:
|
188
|
+
#
|
189
|
+
# set_operand.must_be.subset_of 0..2
|
190
|
+
#
|
191
|
+
# Constrains the union of +set_operand1+ and +set_operand2+ to a
|
192
|
+
# subset of {0, 1, 2} using the SetOperand#union property and
|
193
|
+
# SetConstraintReceiver#subset:
|
194
|
+
#
|
195
|
+
# set_operand1.union(set_operand2).must_be.subset_of 0..2
|
196
|
+
#
|
197
|
+
# Constrains the union of the set operands in +set_enum+ to _not_
|
198
|
+
# equal {0, 1, 2} by using the SetEnumOperand#union property and
|
199
|
+
# an alias of SetConstraintReceiver#==:
|
200
|
+
#
|
201
|
+
# set_enum.union.must_not == 0..2
|
202
|
+
#
|
203
|
+
# The same as above, but alsa specifying that the constraint should be
|
204
|
+
# reified with +bool_operand+:
|
205
|
+
#
|
206
|
+
# set_enum.union.must_not.equal(0..2, :reify => bool_operand)
|
207
|
+
#
|
208
|
+
class SetConstraintReceiver < Gecode::ConstraintReceiver
|
209
|
+
# Raises TypeError unless the left hand side is a set operand.
|
210
|
+
def initialize(model, params) #:nodoc:
|
211
|
+
super
|
212
|
+
|
213
|
+
unless params[:lhs].respond_to? :to_set_var
|
214
|
+
raise TypeError, 'Must have set operand as left hand side.'
|
48
215
|
end
|
49
216
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
# reification depends on the constraint on the right hand side (none
|
64
|
-
# support the strength option as no set constraints do).
|
65
|
-
class CompositeStub < Gecode::Constraints::CompositeStub
|
66
|
-
def initialize(model, params)
|
67
|
-
super(CompositeExpression, model, params)
|
217
|
+
end
|
218
|
+
|
219
|
+
# Utility methods for sets.
|
220
|
+
module Util #:nodoc:
|
221
|
+
module_function
|
222
|
+
def decode_options(options)
|
223
|
+
if options.has_key? :strength
|
224
|
+
raise ArgumentError, 'Set constraints do not support the strength ' +
|
225
|
+
'option.'
|
226
|
+
end
|
227
|
+
if options.has_key? :kind
|
228
|
+
raise ArgumentError, 'Set constraints do not support the kind ' +
|
229
|
+
'option.'
|
68
230
|
end
|
231
|
+
|
232
|
+
Gecode::Util.decode_options(options)
|
69
233
|
end
|
70
234
|
end
|
71
235
|
end
|
@@ -74,5 +238,6 @@ require 'gecoder/interface/constraints/set/domain'
|
|
74
238
|
require 'gecoder/interface/constraints/set/relation'
|
75
239
|
require 'gecoder/interface/constraints/set/cardinality'
|
76
240
|
require 'gecoder/interface/constraints/set/connection'
|
241
|
+
require 'gecoder/interface/constraints/set/include'
|
77
242
|
require 'gecoder/interface/constraints/set/operation'
|
78
243
|
require 'gecoder/interface/constraints/set/channel'
|