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,13 +1,19 @@
|
|
1
|
-
module Gecode::
|
2
|
-
class
|
1
|
+
module Gecode::Int
|
2
|
+
class IntConstraintReceiver
|
3
3
|
alias_method :pre_channel_equals, :==
|
4
4
|
|
5
|
-
# Constrains the integer
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# Constrains the integer operand to be equal to the specified boolean
|
6
|
+
# operand. I.e. constrains the integer operand to be 1 when the boolean
|
7
|
+
# operand is true and 0 if the boolean operand is false.
|
8
|
+
#
|
9
|
+
# ==== Examples
|
10
|
+
#
|
11
|
+
# # The integer operand +int+ must be one exactly when the boolean
|
12
|
+
# # operand +bool+ is true.
|
13
|
+
# int.must == bool
|
8
14
|
def ==(bool, options = {})
|
9
|
-
unless @params[:lhs].
|
10
|
-
bool.
|
15
|
+
unless @params[:lhs].respond_to? :to_int_var and
|
16
|
+
bool.respond_to? :to_bool_var
|
11
17
|
return pre_channel_equals(bool, options)
|
12
18
|
end
|
13
19
|
|
@@ -20,42 +26,26 @@ module Gecode::Constraints::Int
|
|
20
26
|
'constraint.'
|
21
27
|
end
|
22
28
|
|
23
|
-
@params.update(Gecode::
|
29
|
+
@params.update(Gecode::Util.decode_options(options))
|
24
30
|
@params[:rhs] = bool
|
25
31
|
@model.add_constraint Channel::ChannelConstraint.new(@model, @params)
|
26
32
|
end
|
27
33
|
|
28
34
|
alias_comparison_methods
|
29
35
|
|
30
|
-
#
|
31
|
-
|
32
|
-
# channel constraint can also take the following option:
|
33
|
-
#
|
34
|
-
# [:offset] Specifies an offset for the integer variable. If the offset is
|
35
|
-
# set to k then the integer variable takes value i+k exactly
|
36
|
-
# when the variable at index i in the boolean enumration is true
|
37
|
-
# and the rest are false.
|
38
|
-
provide_commutivity(:channel){ |rhs, _| rhs.respond_to? :to_bool_var_array }
|
36
|
+
# Provides commutativity with BoolEnumConstraintReceiver#channel .
|
37
|
+
provide_commutativity(:channel){ |rhs, _| rhs.respond_to? :to_bool_enum }
|
39
38
|
end
|
40
39
|
|
41
40
|
# A module that gathers the classes and modules used in channel constraints
|
42
|
-
# involving a single integer
|
41
|
+
# involving a single integer operand.
|
43
42
|
module Channel #:nodoc:
|
44
|
-
|
45
|
-
# 1 if a boolean variable is true, and 0 when the boolean variable is false.
|
46
|
-
# Does not support negation nor reification.
|
47
|
-
#
|
48
|
-
# == Examples
|
49
|
-
#
|
50
|
-
# # The integer variable +x+ must be one exactly when the boolean
|
51
|
-
# # variable +bool+ is true.
|
52
|
-
# x.must == bool
|
53
|
-
class ChannelConstraint < Gecode::Constraints::Constraint
|
43
|
+
class ChannelConstraint < Gecode::Constraint #:nodoc:
|
54
44
|
def post
|
55
45
|
lhs, rhs = @params.values_at(:lhs, :rhs)
|
56
|
-
Gecode::Raw::channel(@model.active_space, lhs.bind,
|
57
|
-
*propagation_options)
|
46
|
+
Gecode::Raw::channel(@model.active_space, lhs.to_int_var.bind,
|
47
|
+
rhs.to_bool_var.bind, *propagation_options)
|
58
48
|
end
|
59
49
|
end
|
60
50
|
end
|
61
|
-
end
|
51
|
+
end
|
@@ -1,8 +1,34 @@
|
|
1
|
-
module Gecode::
|
2
|
-
class
|
3
|
-
# Creates a domain constraint using the specified domain
|
1
|
+
module Gecode::Int
|
2
|
+
class IntConstraintReceiver
|
3
|
+
# Creates a domain constraint using the specified domain, specified
|
4
|
+
# as an enumeration of integers. The integer operand is constrained
|
5
|
+
# to take a value in the domain. Domains should be specified as
|
6
|
+
# ranges if possible.
|
7
|
+
#
|
8
|
+
# ==== Examples
|
9
|
+
#
|
10
|
+
# # +x+ must be in the range 1..10
|
11
|
+
# x.must_be.in 1..10
|
12
|
+
#
|
13
|
+
# # +x+ must not be in the range -5...5
|
14
|
+
# x.must_not_be.in -5...5
|
15
|
+
#
|
16
|
+
# # Specifies the above, but reifies the constraint with the boolean
|
17
|
+
# # operand +bool+ and specified +value+ as strength.
|
18
|
+
# x.must_not_be.in(-5...5, :reify => bool, :strength => :value)
|
19
|
+
#
|
20
|
+
# # +x+ must be in the enumeration [3,5,7].
|
21
|
+
# x.must_be.in [3,5,7]
|
22
|
+
#
|
23
|
+
# # +x+ must not be in the enumeration [5,6,7,17].
|
24
|
+
# x.must_not_be.in [5,6,7,17]
|
25
|
+
#
|
26
|
+
# # Specifies the above, but reifies the constraint with the boolean
|
27
|
+
# # operand +bool+ and specified +value+ as strength.
|
28
|
+
# x.must_not_be.in([5,6,7,17], :reify => bool, :strength => :value)
|
29
|
+
#
|
4
30
|
def in(domain, options = {})
|
5
|
-
@params.update(Gecode::
|
31
|
+
@params.update(Gecode::Util.decode_options(options))
|
6
32
|
@params[:domain] = domain
|
7
33
|
if domain.kind_of? Range
|
8
34
|
@model.add_constraint Domain::RangeDomainConstraint.new(@model, @params)
|
@@ -17,28 +43,17 @@ module Gecode::Constraints::Int
|
|
17
43
|
|
18
44
|
# A module that gathers the classes and modules used in domain constraints.
|
19
45
|
module Domain #:nodoc:
|
20
|
-
# Range domain constraints specify that an integer
|
21
|
-
# contained within a specified range of integers.
|
22
|
-
|
23
|
-
#
|
24
|
-
# == Examples
|
25
|
-
#
|
26
|
-
# # +x+ must be in the range 1..10
|
27
|
-
# x.must_be.in 1..10
|
28
|
-
#
|
29
|
-
# # +x+ must not be in the range -5...5
|
30
|
-
# x.must_not_be.in -5...5
|
31
|
-
#
|
32
|
-
# # Specifies the above, but but reifies the constraint with the boolean
|
33
|
-
# # variable +bool+ and specified +value+ as strength.
|
34
|
-
# x.must_not_be.in(-5...5, :reify => bool, :strength => :value)
|
35
|
-
class RangeDomainConstraint < Gecode::Constraints::ReifiableConstraint
|
46
|
+
# Range domain constraints specify that an integer operand must be
|
47
|
+
# contained within a specified range of integers.
|
48
|
+
class RangeDomainConstraint < Gecode::ReifiableConstraint #:nodoc:
|
36
49
|
def post
|
37
50
|
var, domain, reif_var = @params.values_at(:lhs, :domain, :reif)
|
38
51
|
|
39
|
-
(params = []) << var.bind
|
40
|
-
|
41
|
-
|
52
|
+
(params = []) << var.to_int_var.bind
|
53
|
+
last = domain.last
|
54
|
+
last -= 1 if domain.exclude_end?
|
55
|
+
params << domain.first << last
|
56
|
+
params << reif_var.to_bool_var.bind if reif_var.respond_to? :to_bool_var
|
42
57
|
params.concat propagation_options
|
43
58
|
|
44
59
|
Gecode::Raw::dom(@model.active_space, *params)
|
@@ -46,27 +61,15 @@ module Gecode::Constraints::Int
|
|
46
61
|
negate_using_reification
|
47
62
|
end
|
48
63
|
|
49
|
-
# Enum domain constraints specify that an integer
|
50
|
-
# in an enumeration of integers.
|
51
|
-
|
52
|
-
# == Examples
|
53
|
-
#
|
54
|
-
# # +x+ must be in the enumeration [3,5,7].
|
55
|
-
# x.must_be.in [3,5,7]
|
56
|
-
#
|
57
|
-
# # +x+ must not be in the enumeration [5,6,7,17].
|
58
|
-
# x.must_not_be.in [5,6,7,17]
|
59
|
-
#
|
60
|
-
# # Specifies the above, but but reifies the constraint with the boolean
|
61
|
-
# # variable +bool+ and specified +value+ as strength.
|
62
|
-
# x.must_not_be.in(-[5,6,7,17], :reify => bool, :strength => :value)
|
63
|
-
class EnumDomainConstraint < Gecode::Constraints::ReifiableConstraint
|
64
|
+
# Enum domain constraints specify that an integer operand must be contained
|
65
|
+
# in an enumeration of integers.
|
66
|
+
class EnumDomainConstraint < Gecode::ReifiableConstraint #:nodoc:
|
64
67
|
def post
|
65
68
|
var, domain, reif_var = @params.values_at(:lhs, :domain, :reif)
|
66
69
|
|
67
|
-
(params = []) << var.bind
|
68
|
-
params << Gecode::
|
69
|
-
params << reif_var.bind if reif_var.respond_to? :
|
70
|
+
(params = []) << var.to_int_var.bind
|
71
|
+
params << Gecode::Util.constant_set_to_int_set(domain)
|
72
|
+
params << reif_var.to_bool_var.bind if reif_var.respond_to? :to_bool_var
|
70
73
|
params.concat propagation_options
|
71
74
|
|
72
75
|
Gecode::Raw::dom(@model.active_space, *params)
|
@@ -74,4 +77,4 @@ module Gecode::Constraints::Int
|
|
74
77
|
negate_using_reification
|
75
78
|
end
|
76
79
|
end
|
77
|
-
end
|
80
|
+
end
|
@@ -1,156 +1,72 @@
|
|
1
|
-
module Gecode
|
2
|
-
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module Gecode::Int
|
2
|
+
module IntOperand
|
3
|
+
# Produces a new IntOperand representing this operand plus
|
4
|
+
# +int_operand_or_fixnum+.
|
5
|
+
#
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# # +int1+ plus +int2+
|
9
|
+
# int1 + int2
|
10
|
+
#
|
11
|
+
# # +int+ plus 17
|
12
|
+
# int + 17
|
13
|
+
def +(int_operand_or_fixnum)
|
14
|
+
int_linear_expression_operation(:+, int_operand_or_fixnum)
|
7
15
|
end
|
8
16
|
|
9
|
-
|
17
|
+
# Produces a new IntOperand representing this operand minus
|
18
|
+
# +int_operand_or_fixnum+.
|
19
|
+
#
|
20
|
+
# ==== Examples
|
21
|
+
#
|
22
|
+
# # +int1+ minus +int2+
|
23
|
+
# int1 - int2
|
24
|
+
#
|
25
|
+
# # +int+ minus 17
|
26
|
+
# int - 17
|
27
|
+
def -(int_operand_or_fixnum)
|
28
|
+
int_linear_expression_operation(:-, int_operand_or_fixnum)
|
29
|
+
end
|
10
30
|
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
31
|
+
# Produces a new IntOperand representing this operand times a
|
32
|
+
# constant.
|
33
|
+
#
|
34
|
+
# ==== Examples
|
35
|
+
#
|
36
|
+
# # +int+ times 17
|
37
|
+
# int * 17
|
38
|
+
def *(fixnum)
|
39
|
+
if fixnum.kind_of? Fixnum
|
40
|
+
int_linear_expression_operation(:*, fixnum)
|
17
41
|
else
|
18
|
-
|
42
|
+
raise TypeError, "Expected fixnum, got #{fixnum.class}."
|
19
43
|
end
|
20
44
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
module Constraints::Int
|
31
|
-
class Expression #:nodoc:
|
32
|
-
# Add some relation selection based on whether the expression is negated.
|
33
|
-
alias_method :pre_linear_initialize, :initialize
|
34
|
-
def initialize(model, params)
|
35
|
-
pre_linear_initialize(model, params)
|
36
|
-
unless params[:negate]
|
37
|
-
@method_relations = Constraints::Util::RELATION_TYPES
|
38
|
-
else
|
39
|
-
@method_relations = Constraints::Util::NEGATED_RELATION_TYPES
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Define the relation methods.
|
44
|
-
Constraints::Util::RELATION_TYPES.each_key do |name|
|
45
|
-
module_eval <<-"end_code"
|
46
|
-
def #{name}(expression, options = {})
|
47
|
-
relation = @method_relations[:#{name}]
|
48
|
-
@params.update(
|
49
|
-
Gecode::Constraints::Util.decode_options(options))
|
50
|
-
if self.simple_expression? and simple_expression?(expression)
|
51
|
-
# A relation constraint is enough.
|
52
|
-
add_relation_constraint(relation, expression)
|
53
|
-
else
|
54
|
-
add_linear_constraint(relation, expression)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end_code
|
58
|
-
end
|
59
|
-
alias_comparison_methods
|
60
|
-
|
61
|
-
protected
|
62
|
-
|
63
|
-
# Checks whether the given expression is simple enough to be used in a
|
64
|
-
# simple relation constraint. Returns true if it is, false otherwise. If
|
65
|
-
# no expression is given then the this expression's left hand side is
|
66
|
-
# checked.
|
67
|
-
def simple_expression?(expression = nil)
|
68
|
-
if expression.nil?
|
69
|
-
simple_expression?(@params[:lhs])
|
70
|
-
else
|
71
|
-
expression.kind_of?(Gecode::FreeIntVar) or
|
72
|
-
expression.kind_of?(Gecode::FreeBoolVar) or
|
73
|
-
expression.kind_of?(Fixnum)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
# Places the linear constraint corresponding to the specified (integer)
|
80
|
-
# relation type (as specified by Gecode) in relation to the specifed
|
81
|
-
# expression.
|
82
|
-
#
|
83
|
-
# Raises TypeError if the element is of a type that doesn't allow a
|
84
|
-
# relation to be specified.
|
85
|
-
def add_linear_constraint(relation_type, right_hand_side)
|
86
|
-
# Bind parameters.
|
87
|
-
lhs = @params[:lhs]
|
88
|
-
if lhs.kind_of?(Gecode::FreeIntVar) or lhs.kind_of?(Gecode::FreeBoolVar)
|
89
|
-
lhs = lhs * 1 # Convert to Gecode::Raw::LinExp
|
90
|
-
end
|
91
|
-
if not (right_hand_side.respond_to? :to_minimodel_lin_exp or
|
92
|
-
right_hand_side.kind_of?(Gecode::FreeIntVar) or
|
93
|
-
right_hand_side.kind_of?(Gecode::FreeBoolVar) or
|
94
|
-
right_hand_side.kind_of?(Fixnum))
|
95
|
-
raise TypeError, 'Invalid right hand side of linear equation.'
|
96
|
-
end
|
97
|
-
|
98
|
-
@params.update(:relation_type => relation_type, :lhs => lhs,
|
99
|
-
:rhs => right_hand_side)
|
100
|
-
@model.add_constraint Linear::LinearConstraint.new(@model, @params)
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Performs the int linear expression operation +operator+ on self
|
49
|
+
# and +operand2+.
|
50
|
+
def int_linear_expression_operation(operator, operand2)
|
51
|
+
unless operand2.respond_to? :to_minimodel_lin_exp
|
52
|
+
operand2 = Linear::ExpressionNode.new operand2
|
101
53
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
# element.
|
106
|
-
def add_relation_constraint(relation_type, element)
|
107
|
-
@model.add_constraint Linear::SimpleRelationConstraint.new(@model,
|
108
|
-
@params.update(:relation_type => relation_type, :element => element))
|
54
|
+
operand1 = self
|
55
|
+
unless operand1.respond_to? :to_minimodel_lin_exp
|
56
|
+
operand1 = Linear::ExpressionNode.new(self, @model)
|
109
57
|
end
|
58
|
+
Linear::ExpressionTree.new(operand1, operand2, operator)
|
110
59
|
end
|
111
60
|
end
|
112
|
-
|
61
|
+
|
113
62
|
# A module that gathers the classes and modules used in linear constraints.
|
114
|
-
module
|
115
|
-
|
116
|
-
# equation containing variables must hold. The same relations and options
|
117
|
-
# used in +SimpleRelationConstraint+ can also be used for linear
|
118
|
-
# constraints.
|
119
|
-
#
|
120
|
-
# Boolean variables can also be used instead of integer variables. In that
|
121
|
-
# case a boolean variable assigned true is equal to 1 and a boolean variable
|
122
|
-
# assigned false is equal to 0. There is one exception: boolean variables
|
123
|
-
# can not be used alone as left hand side.
|
124
|
-
#
|
125
|
-
# Do not mix boolean and integer variables. Even if possible it's not
|
126
|
-
# supported, and might be removed in the future.
|
127
|
-
#
|
128
|
-
# == Examples
|
129
|
-
#
|
130
|
-
# # The sum of the int variables +x+ and +y+ must equal +z+ + 3.
|
131
|
-
# (x + y).must == z + 3
|
132
|
-
#
|
133
|
-
# # Another way of writing the above.
|
134
|
-
# z.must == x + y - 3
|
135
|
-
#
|
136
|
-
# # The inequality 10(x + y) > 3x must not hold.
|
137
|
-
# (x + y)*10.must_not > x*3
|
138
|
-
#
|
139
|
-
# # Specifies the above, but reifies the constraint with the boolean
|
140
|
-
# # variable +bool+ and gives it propagation strength +domain+.
|
141
|
-
# (x + y)*10.must_not_be.greater_than(x*3, :reify => bool, :strength => :domain)
|
142
|
-
class LinearConstraint < Gecode::Constraints::ReifiableConstraint
|
63
|
+
module Linear #:nodoc:
|
64
|
+
class LinearRelationConstraint < Gecode::ReifiableConstraint #:nodoc:
|
143
65
|
def post
|
144
66
|
lhs, rhs, relation_type, reif_var =
|
145
67
|
@params.values_at(:lhs, :rhs, :relation_type, :reif)
|
146
|
-
reif_var = reif_var.bind if reif_var.respond_to? :
|
147
|
-
|
148
|
-
rhs = rhs.to_minimodel_lin_exp
|
149
|
-
elsif rhs.respond_to? :bind
|
150
|
-
rhs = rhs.bind * 1
|
151
|
-
end
|
152
|
-
|
153
|
-
final_exp = (lhs.to_minimodel_lin_exp - rhs)
|
68
|
+
reif_var = reif_var.to_bool_var.bind if reif_var.respond_to? :to_bool_var
|
69
|
+
final_exp = (lhs.to_minimodel_lin_exp - rhs.to_minimodel_lin_exp)
|
154
70
|
if reif_var.nil?
|
155
71
|
final_exp.post(@model.active_space, relation_type,
|
156
72
|
*propagation_options)
|
@@ -161,102 +77,18 @@ module Gecode
|
|
161
77
|
end
|
162
78
|
end
|
163
79
|
|
164
|
-
# Simple relation constraints specify that an integer variable must have a
|
165
|
-
# specified relation to a constant integer or another integer variable. The
|
166
|
-
# following relations are supported (the aliases of each relation are also
|
167
|
-
# listed).
|
168
|
-
#
|
169
|
-
# * <, lesser, lesser_than
|
170
|
-
# * >, greater, greater_than
|
171
|
-
# * >=, greater_or_equal, greater_than_or_equal_to
|
172
|
-
# * <=, less_or_equal, less_than_or_equal_to
|
173
|
-
# * ==, equal, equal_to
|
174
|
-
#
|
175
|
-
# Each can be negated by using +must_not+ instead of +must+.
|
176
|
-
#
|
177
|
-
# Two options (given as a hash) are available:
|
178
|
-
#
|
179
|
-
# [strength] Specifies the propagation strength of the constraint. Must be
|
180
|
-
# one of +value+, +bounds+, +domain+ and +default+. The
|
181
|
-
# strength generally progresses as +value+ -> +bounds+ ->
|
182
|
-
# +domain+ (+value+ being the weakest, but usually cheapest,
|
183
|
-
# while +domain+ is the strongest but usually costly).
|
184
|
-
# [reify] Specifies a boolean variable that should be used for
|
185
|
-
# reification (see +ReifiableConstraint+).
|
186
|
-
#
|
187
|
-
# == Examples
|
188
|
-
#
|
189
|
-
# # Int variable +x+ must not equal 0.
|
190
|
-
# x.must_not.equal(0)
|
191
|
-
#
|
192
|
-
# # Another way of writing the above.
|
193
|
-
# x.must_not == 0
|
194
|
-
#
|
195
|
-
# # +x+ must be strictly larger than +y+.
|
196
|
-
# x.must > y
|
197
|
-
#
|
198
|
-
# # Specifies the above, but reifies the constraint with the boolean
|
199
|
-
# # variable +bool+.
|
200
|
-
# x.must_be.greater_than(y, :reify => bool)
|
201
|
-
class SimpleRelationConstraint < Gecode::Constraints::ReifiableConstraint
|
202
|
-
def post
|
203
|
-
# Fetch the parameters to Gecode.
|
204
|
-
lhs, relation, rhs, reif_var =
|
205
|
-
@params.values_at(:lhs, :relation_type, :element, :reif)
|
206
|
-
|
207
|
-
rhs = rhs.bind if rhs.respond_to? :bind
|
208
|
-
if reif_var.nil?
|
209
|
-
Gecode::Raw::rel(@model.active_space, lhs.bind, relation, rhs,
|
210
|
-
*propagation_options)
|
211
|
-
else
|
212
|
-
Gecode::Raw::rel(@model.active_space, lhs.bind, relation, rhs,
|
213
|
-
reif_var.bind, *propagation_options)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
# Helper methods for linear expressions. Classes mixing in this module must
|
219
|
-
# have a method #model which gives the model the expression is operating in.
|
220
|
-
module Helper #:nodoc:
|
221
|
-
include Gecode::Constraints::LeftHandSideMethods
|
222
|
-
|
223
|
-
private
|
224
|
-
|
225
|
-
OPERATION_TYPES = [:+, :-, :*]
|
226
|
-
|
227
|
-
public
|
228
|
-
|
229
|
-
# Define methods for the available operations.
|
230
|
-
OPERATION_TYPES.each do |name|
|
231
|
-
module_eval <<-"end_code"
|
232
|
-
def #{name}(expression)
|
233
|
-
unless expression.kind_of? ExpressionTree
|
234
|
-
expression = ExpressionNode.new(expression)
|
235
|
-
end
|
236
|
-
ExpressionTree.new(self, expression, :#{name})
|
237
|
-
end
|
238
|
-
end_code
|
239
|
-
end
|
240
|
-
|
241
|
-
private
|
242
|
-
|
243
|
-
# Produces an expression for the lhs module.
|
244
|
-
def expression(params)
|
245
|
-
params.update(:lhs => self)
|
246
|
-
Gecode::Constraints::Int::Expression.new(model, params)
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
80
|
# Describes a binary tree of expression nodes which together form a linear
|
251
81
|
# expression.
|
252
|
-
class ExpressionTree #:nodoc:
|
253
|
-
|
254
|
-
|
255
|
-
# Constructs a new expression with the specified
|
82
|
+
class ExpressionTree < Gecode::Int::ShortCircuitRelationsOperand #:nodoc:
|
83
|
+
attr :model
|
84
|
+
|
85
|
+
# Constructs a new expression with the specified operands.
|
256
86
|
def initialize(left_node, right_node, operation)
|
87
|
+
super(left_node.model || right_node.model)
|
257
88
|
@left = left_node
|
258
89
|
@right = right_node
|
259
90
|
@operation = operation
|
91
|
+
@model = @left.model || @right.model
|
260
92
|
end
|
261
93
|
|
262
94
|
# Converts the linear expression to an instance of
|
@@ -264,20 +96,35 @@ module Gecode
|
|
264
96
|
def to_minimodel_lin_exp
|
265
97
|
@left.to_minimodel_lin_exp.send(@operation, @right.to_minimodel_lin_exp)
|
266
98
|
end
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
99
|
+
|
100
|
+
def relation_constraint(relation, int_operand_or_fix, params)
|
101
|
+
unless params[:negate]
|
102
|
+
relation_type =
|
103
|
+
Gecode::Util::RELATION_TYPES[relation]
|
104
|
+
else
|
105
|
+
relation_type =
|
106
|
+
Gecode::Util::NEGATED_RELATION_TYPES[relation]
|
107
|
+
end
|
108
|
+
|
109
|
+
unless int_operand_or_fix.respond_to? :to_minimodel_lin_exp
|
110
|
+
int_operand_or_fix = Linear::ExpressionNode.new(int_operand_or_fix);
|
111
|
+
end
|
112
|
+
|
113
|
+
params.update(:lhs => self, :rhs => int_operand_or_fix,
|
114
|
+
:relation_type => relation_type)
|
115
|
+
LinearRelationConstraint.new(model, params)
|
271
116
|
end
|
272
117
|
end
|
273
118
|
|
274
119
|
# Describes a single node in a linear expression.
|
275
120
|
class ExpressionNode #:nodoc:
|
276
|
-
include Helper
|
277
|
-
|
278
121
|
attr :model
|
279
122
|
|
280
123
|
def initialize(value, model = nil)
|
124
|
+
unless value.respond_to?(:to_int_var) or value.kind_of?(Fixnum)
|
125
|
+
raise TypeError, 'Expected int operand or fixnum, ' +
|
126
|
+
"got #{value.class}."
|
127
|
+
end
|
281
128
|
@value = value
|
282
129
|
@model = model
|
283
130
|
end
|
@@ -286,12 +133,11 @@ module Gecode
|
|
286
133
|
# Gecode::Raw::MiniModel::LinExpr
|
287
134
|
def to_minimodel_lin_exp
|
288
135
|
expression = @value
|
289
|
-
if expression.respond_to? :
|
290
|
-
|
291
|
-
expression = expression.bind * 1
|
136
|
+
if expression.respond_to? :to_int_var
|
137
|
+
expression = expression.to_int_var.bind * 1
|
292
138
|
end
|
293
139
|
expression
|
294
140
|
end
|
295
141
|
end
|
296
142
|
end
|
297
|
-
end
|
143
|
+
end
|