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,36 +1,60 @@
|
|
1
|
-
module Gecode::
|
2
|
-
class
|
3
|
-
#
|
4
|
-
# can
|
1
|
+
module Gecode::IntEnum
|
2
|
+
class IntEnumConstraintReceiver
|
3
|
+
# Constrains the elements in this enumeration to be sorted in ascending
|
4
|
+
# order. The following options can be given in addition to the
|
5
|
+
# common constraint options:
|
5
6
|
#
|
6
|
-
# [:as] Defines a target (must be an
|
7
|
+
# [:as] Defines a target (must be an IntEnum) that will
|
7
8
|
# hold the sorted version of the original enumerable. The original
|
8
9
|
# enumerable will not be affected (i.e. will not necessarily be
|
9
10
|
# sorted)
|
10
|
-
# [:order] Sets an
|
11
|
-
# order of the original enum's
|
11
|
+
# [:order] Sets an IntEnum that should be used to store the
|
12
|
+
# order of the original enum's operands when sorted. The original
|
12
13
|
# enumerable will not be affected (i.e. will not necessarily be
|
13
14
|
# sorted)
|
14
15
|
#
|
15
16
|
# If neither of those options are specified then the original enumerable
|
16
17
|
# will be constrained to be sorted (otherwise not). Sort constraints with
|
17
18
|
# options do not allow negation.
|
19
|
+
#
|
20
|
+
# ==== Examples
|
21
|
+
#
|
22
|
+
# # Constrain +numbers+ to be sorted.
|
23
|
+
# numbers.must_be.sorted
|
24
|
+
#
|
25
|
+
# # Constrain +numbers+ to not be sorted.
|
26
|
+
# numbers.must_not_be.sorted
|
27
|
+
#
|
28
|
+
# # Constrain +sorted_numbers+ to be a sorted version of +numbers+.
|
29
|
+
# numbers.must_be.sorted(:as => sorted_numbers)
|
30
|
+
#
|
31
|
+
# # Constrain +order+ to be the order in which +numbers+ has to be
|
32
|
+
# # ordered to be sorted.
|
33
|
+
# numbers.must_be.sorted(:order => order)
|
34
|
+
#
|
35
|
+
# # Constrain +sorted_numbers+ to be +numbers+ sorted in the order
|
36
|
+
# # described by the IntEnum +order+.
|
37
|
+
# numbers.must_be.sorted(:as => sorted_numbers, :order => order)
|
38
|
+
#
|
39
|
+
# # Constrains +numbers+ to be sorted, reifying with the boolean
|
40
|
+
# # operand +is_sorted+, while selecting +domain+ as strength.
|
41
|
+
# numbers.must_be.sorted(:reify => :is_sorted, :strength => :domain)
|
18
42
|
def sorted(options = {})
|
19
43
|
# Extract and check options.
|
20
44
|
target = options.delete(:as)
|
21
45
|
order = options.delete(:order)
|
22
|
-
unless target.nil? or target.respond_to? :
|
46
|
+
unless target.nil? or target.respond_to? :to_int_enum
|
23
47
|
raise TypeError, 'Expected int var enum as :as, got ' +
|
24
48
|
"#{target.class}."
|
25
49
|
end
|
26
|
-
unless order.nil? or order.respond_to? :
|
50
|
+
unless order.nil? or order.respond_to? :to_int_enum
|
27
51
|
raise TypeError, 'Expected int var enum as :order, got ' +
|
28
52
|
"#{order.class}."
|
29
53
|
end
|
30
54
|
|
31
55
|
# Extract standard options and convert to constraint.
|
32
56
|
reified = !options[:reify].nil?
|
33
|
-
@params.update(Gecode::
|
57
|
+
@params.update(Gecode::Util.decode_options(options))
|
34
58
|
if target.nil? and order.nil?
|
35
59
|
@model.add_constraint Sort::SortConstraint.new(@model, @params)
|
36
60
|
else
|
@@ -53,33 +77,18 @@ module Gecode::Constraints::IntEnum
|
|
53
77
|
|
54
78
|
# A module that gathers the classes and modules used in sort constraints.
|
55
79
|
module Sort #:nodoc:
|
56
|
-
|
57
|
-
# integer variables to be the sorted version of another set of integer
|
58
|
-
# variables. Optionally a third enumeration may be used to define the order
|
59
|
-
# in which the the variables should be sorted.
|
60
|
-
#
|
61
|
-
# Neither negation nor reification is supported.
|
62
|
-
#
|
63
|
-
# == Example
|
64
|
-
#
|
65
|
-
# # Constrains +sorted_numbers+ to be a sorted version of +numbers+.
|
66
|
-
# numbers.must_be.sorted(:as => sorted_numbers)
|
67
|
-
#
|
68
|
-
# # Constrains +sorted_numbers+ to be +numbers+ sorted in the order
|
69
|
-
# # described by the integer variable enumeration +order+.
|
70
|
-
# numbers.must_be.sorted(:as => sorted_numbers, :order => order)
|
71
|
-
class SortConstraintWithOptions < Gecode::Constraints::Constraint
|
80
|
+
class SortConstraintWithOptions < Gecode::Constraint #:nodoc:
|
72
81
|
def post
|
73
82
|
if @params[:target].nil?
|
74
83
|
# We must have a target.
|
75
|
-
lhs = @params[:lhs]
|
84
|
+
lhs = @params[:lhs].to_int_enum
|
76
85
|
@params[:target] = @model.int_var_array(lhs.size, lhs.domain_range)
|
77
86
|
end
|
78
87
|
|
79
88
|
# Prepare the parameters.
|
80
89
|
params = @params.values_at(:lhs, :target, :order).map do |param|
|
81
|
-
if param.respond_to? :
|
82
|
-
param.
|
90
|
+
if param.respond_to? :to_int_enum
|
91
|
+
param.to_int_enum.bind_array
|
83
92
|
else
|
84
93
|
param
|
85
94
|
end
|
@@ -91,19 +100,7 @@ module Gecode::Constraints::IntEnum
|
|
91
100
|
end
|
92
101
|
end
|
93
102
|
|
94
|
-
|
95
|
-
# variables to be sorted. Supports reification and negation.
|
96
|
-
#
|
97
|
-
# == Example
|
98
|
-
#
|
99
|
-
# # Constrains the variables in +int_enum+ to be sorted ascendingly.
|
100
|
-
# int_enum.must_be.sorted
|
101
|
-
#
|
102
|
-
# # Reifies the constraint that the variables in +int_enum+ to be sorted
|
103
|
-
# # ascendingly with the boolean variable +is_sorted+, while selecting
|
104
|
-
# # +domain+ as strength.
|
105
|
-
# int_enum.must_be.sorted(:reify => :is_sorted, :strength => :domain)
|
106
|
-
class SortConstraint < Gecode::Constraints::ReifiableConstraint
|
103
|
+
class SortConstraint < Gecode::ReifiableConstraint #:nodoc:
|
107
104
|
def post
|
108
105
|
lhs, strength, kind, reif_var =
|
109
106
|
@params.values_at(:lhs, :strength, :kind, :reif)
|
@@ -112,9 +109,9 @@ module Gecode::Constraints::IntEnum
|
|
112
109
|
# We translate the constraint into n-1 relation constraints.
|
113
110
|
options = {
|
114
111
|
:strength =>
|
115
|
-
Gecode::
|
112
|
+
Gecode::Util::PROPAGATION_STRENGTHS.invert[strength],
|
116
113
|
:kind =>
|
117
|
-
Gecode::
|
114
|
+
Gecode::Util::PROPAGATION_KINDS.invert[kind]
|
118
115
|
}
|
119
116
|
if using_reification
|
120
117
|
reification_variables = @model.bool_var_array(lhs.size - 1)
|
@@ -135,4 +132,4 @@ module Gecode::Constraints::IntEnum
|
|
135
132
|
negate_using_reification
|
136
133
|
end
|
137
134
|
end
|
138
|
-
end
|
135
|
+
end
|
@@ -1,28 +1,85 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# A module containing constraints that have enumerations of integer
|
2
|
+
# operands as left hand side.
|
3
|
+
module Gecode::IntEnum #:nodoc:
|
4
|
+
# A IntEnumOperand is a enumeration of IntOperand on which the
|
5
|
+
# constraints defined in IntEnumConstraintReceiver can be placed.
|
6
|
+
#
|
7
|
+
# Enumerations of integer operands can be created either by using
|
8
|
+
# Gecode::Model#int_var_array and Gecode::Model#int_var_matrix, or
|
9
|
+
# by wrapping an existing enumeration containing IntOperand using
|
10
|
+
# Gecode::Model#wrap_enum. The enumerations, no matter how they were
|
11
|
+
# created, all respond to the properties defined by IntEnumOperand.
|
12
|
+
#
|
13
|
+
# ==== Examples
|
14
|
+
#
|
15
|
+
# Produces an array of five int operands with domain 0..9 inside a
|
16
|
+
# problem formulation using Gecode::Model#int_var_array:
|
17
|
+
#
|
18
|
+
# int_enum = int_var_array(5, 0..9)
|
19
|
+
#
|
20
|
+
# Uses Gecode::Model#wrap_enum inside a problem formulation to create
|
21
|
+
# a IntEnumOperand from an existing enumeration containing the
|
22
|
+
# integer operands +int_operand1+ and +int_operand2+:
|
23
|
+
#
|
24
|
+
# int_enum = wrap_enum([int_operand1, int_operand2])
|
25
|
+
#
|
26
|
+
#--
|
27
|
+
# Classes that mix in IntEnumOperand must define #model and
|
28
|
+
# #to_int_enum .
|
29
|
+
module IntEnumOperand
|
30
|
+
include Gecode::Operand
|
31
|
+
|
32
|
+
def method_missing(method, *args) #:nodoc:
|
33
|
+
if Gecode::IntEnum::Dummy.instance_methods.include? method.to_s
|
34
|
+
# Delegate to the int enum.
|
35
|
+
to_int_enum.method(method).call(*args)
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
5
41
|
private
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
params.update(:lhs => self)
|
10
|
-
Constraints::IntEnum::Expression.new(@model, params)
|
42
|
+
|
43
|
+
def construct_receiver(params)
|
44
|
+
IntEnumConstraintReceiver.new(@model, params)
|
11
45
|
end
|
12
46
|
end
|
13
|
-
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
47
|
+
|
48
|
+
# IntEnumConstraintReceiver contains all constraints that can be
|
49
|
+
# placed on a IntEnumOperand.
|
50
|
+
#
|
51
|
+
# Constraints are placed by calling IntEnumOperand#must (or any other
|
52
|
+
# of the variations defined in Operand), which produces a
|
53
|
+
# IntEnumConstraintReceiver from which the desired constraint can be used.
|
54
|
+
#
|
55
|
+
# Some constraint accepts a number of options. See ConstraintReceiver
|
56
|
+
# for more information.
|
57
|
+
#
|
58
|
+
# ==== Examples
|
59
|
+
#
|
60
|
+
# Constrains the integer operands in +int_enum+ to take on different
|
61
|
+
# values by using IntEnumConstraintReceiver#distinct:
|
62
|
+
#
|
63
|
+
# int_enum.must_be.distinct
|
64
|
+
#
|
65
|
+
# Constrains +int_enum2+ to have the same elements as +int_enum+, but
|
66
|
+
# sorted in ascending order. Uses IntEnumConstraintReceiver#sorted:
|
67
|
+
#
|
68
|
+
# int_enum.must_be.sorted(:as => int_enum2)
|
69
|
+
#
|
70
|
+
# The same as above, but specifying that strength :domain should be
|
71
|
+
# used and that the constraint should be reified with +bool_operand+:
|
72
|
+
#
|
73
|
+
# int_enum.must_be.sorted(:as => int_enum2, :strength => :domain, :reify => bool_operand)
|
74
|
+
#
|
75
|
+
class IntEnumConstraintReceiver < Gecode::ConstraintReceiver
|
76
|
+
# Raises TypeError unless the left hand side is an int enum
|
77
|
+
# operand.
|
78
|
+
def initialize(model, params) #:nodoc:
|
79
|
+
super
|
80
|
+
|
81
|
+
unless params[:lhs].respond_to? :to_int_enum
|
82
|
+
raise TypeError, 'Must have int enum operand as left hand side.'
|
26
83
|
end
|
27
84
|
end
|
28
85
|
end
|
@@ -1,58 +1,229 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# A module that deals with the operands, properties and constraints of
|
2
|
+
# integer variables.
|
3
|
+
module Gecode::Int #:nodoc:
|
4
|
+
# A IntOperand is a combination of variables on which the
|
5
|
+
# constraints defined in IntConstraintReceiver can be placed.
|
6
|
+
#
|
7
|
+
# Integer operands can be created either by using
|
8
|
+
# Gecode::Model#int_var et al, or by using properties that produce
|
9
|
+
# integer operands. The operands, no matter how they were created,
|
10
|
+
# all respond to the properties defined by IntOperand.
|
11
|
+
#
|
12
|
+
# ==== Examples
|
13
|
+
#
|
14
|
+
# Produces a single integer operand (more specifically an IntVar) with
|
15
|
+
# domain 0..9 inside a problem formulation, using
|
16
|
+
# Gecode::Model#int_var:
|
17
|
+
#
|
18
|
+
# int_operand = int_var(0..9)
|
19
|
+
#
|
20
|
+
# Uses the IntOperand#+ property to produce a new integer
|
21
|
+
# operand representing +int_operand1+ plus +int_operand2+:
|
22
|
+
#
|
23
|
+
# new_int_operand = int_operand1 + int_operand2
|
24
|
+
#
|
25
|
+
# Uses the IntEnumOperand#max property to produce a new
|
26
|
+
# integer operand representing the maximum value of the integer operands
|
27
|
+
# in the enumeration +int_enum+:
|
28
|
+
#
|
29
|
+
# new_int_operand = int_enum.max
|
30
|
+
#
|
31
|
+
# Uses the IntEnumOperand#[] property to produce a new integer operand
|
32
|
+
# representing the integer operand at the index decided by
|
33
|
+
# +int_operand+ (which can change during search) in the enumeration
|
34
|
+
# +int_enum+:
|
35
|
+
#
|
36
|
+
# new_int_operand = int_enum[int_operand]
|
37
|
+
#
|
38
|
+
# Uses the SetOperand#size property to produce a new integer operand
|
39
|
+
# representing the size of +set_operand+:
|
40
|
+
#
|
41
|
+
# new_int_operand = set_operand.size
|
42
|
+
#
|
43
|
+
#--
|
44
|
+
# Classes that mix in IntOperand must define #model and #to_int_var .
|
45
|
+
module IntOperand
|
46
|
+
include Gecode::Operand
|
47
|
+
|
48
|
+
def method_missing(method, *args) #:nodoc:
|
49
|
+
if Gecode::IntVar.instance_methods.include? method.to_s
|
50
|
+
# Delegate to the int var.
|
51
|
+
to_int_var.method(method).call(*args)
|
52
|
+
else
|
53
|
+
super
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
5
57
|
private
|
6
|
-
|
7
|
-
|
8
|
-
|
58
|
+
|
59
|
+
def construct_receiver(params)
|
60
|
+
IntConstraintReceiver.new(model, params)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# An operand that short circuits integer equality.
|
65
|
+
class ShortCircuitEqualityOperand #:nodoc:
|
66
|
+
include Gecode::Int::IntOperand
|
67
|
+
attr :model
|
68
|
+
|
69
|
+
def initialize(model)
|
70
|
+
@model = model
|
71
|
+
end
|
72
|
+
|
73
|
+
def construct_receiver(params)
|
9
74
|
params.update(:lhs => self)
|
10
|
-
|
75
|
+
receiver = IntConstraintReceiver.new(@model, params)
|
76
|
+
op = self
|
77
|
+
receiver.instance_eval{ @short_circuit = op }
|
78
|
+
class <<receiver
|
79
|
+
alias_method :equality_without_short_circuit, :==
|
80
|
+
def ==(operand, options = {})
|
81
|
+
if !@params[:negate] and options[:reify].nil? and
|
82
|
+
operand.respond_to? :to_int_var
|
83
|
+
# Short circuit the constraint.
|
84
|
+
@params.update Gecode::Util.decode_options(options)
|
85
|
+
@model.add_constraint(Gecode::BlockConstraint.new(
|
86
|
+
@model, @params) do
|
87
|
+
@short_circuit.constrain_equal(operand, false,
|
88
|
+
@params.values_at(:strength, :kind))
|
89
|
+
end)
|
90
|
+
else
|
91
|
+
equality_without_short_circuit(operand, options)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
alias_comparison_methods
|
95
|
+
end
|
96
|
+
|
97
|
+
return receiver
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_int_var
|
101
|
+
variable = model.int_var
|
102
|
+
options =
|
103
|
+
Gecode::Util.decode_options({}).values_at(:strength, :kind)
|
104
|
+
model.add_interaction do
|
105
|
+
constrain_equal(variable, true, options)
|
106
|
+
end
|
107
|
+
return variable
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
# Constrains this operand to equal +int_operand+ using the
|
113
|
+
# specified +propagation_options+. If +constrain_domain+ is true
|
114
|
+
# then the method should also attempt to constrain the bounds of the
|
115
|
+
# domain of +int_operand+.
|
116
|
+
def constrain_equal(int_operand, constrain_domain, propagation_options)
|
117
|
+
raise NotImplementedError, 'Abstract method has not been implemented.'
|
11
118
|
end
|
12
119
|
end
|
13
|
-
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
120
|
+
|
121
|
+
# An operand that short circuits integer relation constraints.
|
122
|
+
class ShortCircuitRelationsOperand #:nodoc:
|
123
|
+
include Gecode::Int::IntOperand
|
124
|
+
attr :model
|
125
|
+
|
126
|
+
def initialize(model)
|
127
|
+
@model = model
|
128
|
+
end
|
129
|
+
|
130
|
+
def construct_receiver(params)
|
131
|
+
receiver = IntConstraintReceiver.new(@model, params)
|
132
|
+
op = self
|
133
|
+
receiver.instance_eval{ @short_circuit = op }
|
134
|
+
class <<receiver
|
135
|
+
Gecode::Util::COMPARISON_ALIASES.keys.each do |comp|
|
136
|
+
eval <<-end_code
|
137
|
+
alias_method :alias_#{comp.to_i}_without_short_circuit, :#{comp}
|
138
|
+
def #{comp}(operand, options = {})
|
139
|
+
if operand.respond_to?(:to_int_var) or operand.kind_of? Fixnum
|
140
|
+
# Short circuit the constraint.
|
141
|
+
@params.update Gecode::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
|
150
|
+
end
|
151
|
+
alias_comparison_methods
|
31
152
|
end
|
153
|
+
|
154
|
+
return receiver
|
155
|
+
end
|
156
|
+
|
157
|
+
def to_int_var
|
158
|
+
variable = model.int_var
|
159
|
+
params = {}
|
160
|
+
params.update Gecode::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 +int_operand_or_fix+, which is either an integer
|
167
|
+
# operand or a fixnum, given the specified hash +params+ of parameters.
|
168
|
+
def relation_constraint(relation, int_operand_or_fix, params)
|
169
|
+
raise NotImplementedError, 'Abstract method has not been implemented.'
|
32
170
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
171
|
+
end
|
172
|
+
|
173
|
+
# IntConstraintReceiver contains all constraints that can be
|
174
|
+
# placed on an IntOperand.
|
175
|
+
#
|
176
|
+
# Constraints are placed by calling IntOperand#must (or any other
|
177
|
+
# of the variations defined in Operand), which produces a
|
178
|
+
# IntConstraintReceiver from which the desired constraint can be used.
|
179
|
+
#
|
180
|
+
# Each constraint accepts a number of options. See ConstraintReceiver
|
181
|
+
# for more information.
|
182
|
+
#
|
183
|
+
# ==== Examples
|
184
|
+
#
|
185
|
+
# Constrains +int_operand+ to be strictly greater than 5 using
|
186
|
+
# IntConstraintReceiver#>:
|
187
|
+
#
|
188
|
+
# int_operand.must > 5
|
189
|
+
#
|
190
|
+
# Constrains +int_operand1+ plus +int_operand2+ to be strictly
|
191
|
+
# greater than 5 using the IntOperand#+ property and
|
192
|
+
# IntConstraintReceiver#>:
|
193
|
+
#
|
194
|
+
# (int_operand1 + int_operand2).must > 5
|
195
|
+
#
|
196
|
+
# Constrains the maximum value of the integer operands in +int_enum+ to
|
197
|
+
# _not_ be in the range 3..7 using the IntEnumOperand#max property and
|
198
|
+
# IntConstraintReceiver#in:
|
199
|
+
#
|
200
|
+
# int_enum.max.must_not_be.in 3..7
|
201
|
+
#
|
202
|
+
# Constrains the integer operand at position +int_operand+ in
|
203
|
+
# +int_enum+, an enumeration of integer operands, to be greater than
|
204
|
+
# or equal to +int_operand2+. This uses the IntEnumOperand#[] property
|
205
|
+
# and IntConstraintReceiver#>=:
|
206
|
+
#
|
207
|
+
# int_enum[int_operand].must >= int_operand2
|
208
|
+
#
|
209
|
+
# The same as above, but specifying that strength :domain should be
|
210
|
+
# used and that the constraint should be reified with +bool_operand+:
|
211
|
+
#
|
212
|
+
# int_enum[int_operand].must_be.greater_or_equal(int_operand2, :strength => :domain, :reify => bool_operand)
|
213
|
+
#
|
214
|
+
class IntConstraintReceiver < Gecode::ConstraintReceiver
|
215
|
+
# Raises TypeError unless the left hand side is an int operand.
|
216
|
+
def initialize(model, params) #:nodoc:
|
217
|
+
super
|
218
|
+
|
219
|
+
unless params[:lhs].respond_to? :to_int_var
|
220
|
+
raise TypeError, 'Must have int operand as left hand side.'
|
51
221
|
end
|
52
222
|
end
|
53
223
|
end
|
54
224
|
end
|
55
225
|
|
226
|
+
require 'gecoder/interface/constraints/int/relation'
|
56
227
|
require 'gecoder/interface/constraints/int/linear'
|
57
228
|
require 'gecoder/interface/constraints/int/domain'
|
58
229
|
require 'gecoder/interface/constraints/int/arithmetic'
|