gecoder-with-gecode 0.7.1-mswin32

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.
Files changed (159) hide show
  1. data/CHANGES +81 -0
  2. data/COPYING +17 -0
  3. data/LGPL-LICENSE +458 -0
  4. data/README +45 -0
  5. data/Rakefile +13 -0
  6. data/example/example_helper.rb +1 -0
  7. data/example/magic_sequence.rb +43 -0
  8. data/example/queens.rb +43 -0
  9. data/example/raw_bindings.rb +42 -0
  10. data/example/send_more_money.rb +43 -0
  11. data/example/send_most_money.rb +58 -0
  12. data/example/square_tiling.rb +84 -0
  13. data/example/sudoku-set.rb +110 -0
  14. data/example/sudoku.rb +61 -0
  15. data/lib/gecode.dll +0 -0
  16. data/lib/gecoder.rb +5 -0
  17. data/lib/gecoder/bindings.rb +54 -0
  18. data/lib/gecoder/bindings/bindings.rb +2210 -0
  19. data/lib/gecoder/interface.rb +8 -0
  20. data/lib/gecoder/interface/binding_changes.rb +313 -0
  21. data/lib/gecoder/interface/branch.rb +152 -0
  22. data/lib/gecoder/interface/constraints.rb +397 -0
  23. data/lib/gecoder/interface/constraints/bool/boolean.rb +246 -0
  24. data/lib/gecoder/interface/constraints/bool/linear.rb +29 -0
  25. data/lib/gecoder/interface/constraints/bool_enum/boolean.rb +84 -0
  26. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +8 -0
  27. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +75 -0
  28. data/lib/gecoder/interface/constraints/int/arithmetic.rb +71 -0
  29. data/lib/gecoder/interface/constraints/int/domain.rb +78 -0
  30. data/lib/gecoder/interface/constraints/int/linear.rb +295 -0
  31. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +72 -0
  32. data/lib/gecoder/interface/constraints/int_enum/channel.rb +100 -0
  33. data/lib/gecoder/interface/constraints/int_enum/count.rb +92 -0
  34. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +69 -0
  35. data/lib/gecoder/interface/constraints/int_enum/element.rb +82 -0
  36. data/lib/gecoder/interface/constraints/int_enum/equality.rb +38 -0
  37. data/lib/gecoder/interface/constraints/int_enum/sort.rb +126 -0
  38. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +37 -0
  39. data/lib/gecoder/interface/constraints/int_var_constraints.rb +58 -0
  40. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
  41. data/lib/gecoder/interface/constraints/set/cardinality.rb +75 -0
  42. data/lib/gecoder/interface/constraints/set/connection.rb +193 -0
  43. data/lib/gecoder/interface/constraints/set/domain.rb +109 -0
  44. data/lib/gecoder/interface/constraints/set/operation.rb +132 -0
  45. data/lib/gecoder/interface/constraints/set/relation.rb +178 -0
  46. data/lib/gecoder/interface/constraints/set_enum/channel.rb +18 -0
  47. data/lib/gecoder/interface/constraints/set_enum/distinct.rb +80 -0
  48. data/lib/gecoder/interface/constraints/set_enum/operation.rb +60 -0
  49. data/lib/gecoder/interface/constraints/set_enum/selection.rb +217 -0
  50. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +34 -0
  51. data/lib/gecoder/interface/constraints/set_var_constraints.rb +72 -0
  52. data/lib/gecoder/interface/enum_matrix.rb +64 -0
  53. data/lib/gecoder/interface/enum_wrapper.rb +153 -0
  54. data/lib/gecoder/interface/model.rb +251 -0
  55. data/lib/gecoder/interface/search.rb +123 -0
  56. data/lib/gecoder/interface/variables.rb +254 -0
  57. data/lib/gecoder/version.rb +4 -0
  58. data/specs/binding_changes.rb +76 -0
  59. data/specs/bool_var.rb +74 -0
  60. data/specs/branch.rb +170 -0
  61. data/specs/constraints/arithmetic.rb +266 -0
  62. data/specs/constraints/bool_enum.rb +140 -0
  63. data/specs/constraints/boolean.rb +232 -0
  64. data/specs/constraints/cardinality.rb +154 -0
  65. data/specs/constraints/channel.rb +126 -0
  66. data/specs/constraints/connection.rb +373 -0
  67. data/specs/constraints/constraint_helper.rb +180 -0
  68. data/specs/constraints/constraints.rb +74 -0
  69. data/specs/constraints/count.rb +139 -0
  70. data/specs/constraints/distinct.rb +218 -0
  71. data/specs/constraints/element.rb +106 -0
  72. data/specs/constraints/equality.rb +31 -0
  73. data/specs/constraints/int_domain.rb +69 -0
  74. data/specs/constraints/int_relation.rb +78 -0
  75. data/specs/constraints/linear.rb +332 -0
  76. data/specs/constraints/reification_sugar.rb +96 -0
  77. data/specs/constraints/selection.rb +292 -0
  78. data/specs/constraints/set_domain.rb +181 -0
  79. data/specs/constraints/set_operation.rb +285 -0
  80. data/specs/constraints/set_relation.rb +201 -0
  81. data/specs/constraints/sort.rb +175 -0
  82. data/specs/distribution.rb +14 -0
  83. data/specs/enum_matrix.rb +43 -0
  84. data/specs/enum_wrapper.rb +122 -0
  85. data/specs/int_var.rb +144 -0
  86. data/specs/logging.rb +24 -0
  87. data/specs/model.rb +190 -0
  88. data/specs/search.rb +246 -0
  89. data/specs/set_var.rb +68 -0
  90. data/specs/spec_helper.rb +93 -0
  91. data/tasks/all_tasks.rb +1 -0
  92. data/tasks/building.howto +65 -0
  93. data/tasks/distribution.rake +156 -0
  94. data/tasks/rcov.rake +17 -0
  95. data/tasks/specs.rake +15 -0
  96. data/tasks/svn.rake +11 -0
  97. data/tasks/website.rake +51 -0
  98. data/vendor/gecode/win32/lib/libgecodeint.dll +0 -0
  99. data/vendor/gecode/win32/lib/libgecodekernel.dll +0 -0
  100. data/vendor/gecode/win32/lib/libgecodeminimodel.dll +0 -0
  101. data/vendor/gecode/win32/lib/libgecodesearch.dll +0 -0
  102. data/vendor/gecode/win32/lib/libgecodeset.dll +0 -0
  103. data/vendor/rust/README +28 -0
  104. data/vendor/rust/bin/cxxgenerator.rb +93 -0
  105. data/vendor/rust/include/rust_checks.hh +115 -0
  106. data/vendor/rust/include/rust_conversions.hh +102 -0
  107. data/vendor/rust/rust.rb +67 -0
  108. data/vendor/rust/rust/attribute.rb +51 -0
  109. data/vendor/rust/rust/bindings.rb +172 -0
  110. data/vendor/rust/rust/class.rb +339 -0
  111. data/vendor/rust/rust/constants.rb +48 -0
  112. data/vendor/rust/rust/container.rb +110 -0
  113. data/vendor/rust/rust/cppifaceparser.rb +129 -0
  114. data/vendor/rust/rust/cwrapper.rb +72 -0
  115. data/vendor/rust/rust/cxxclass.rb +98 -0
  116. data/vendor/rust/rust/element.rb +81 -0
  117. data/vendor/rust/rust/enum.rb +63 -0
  118. data/vendor/rust/rust/function.rb +407 -0
  119. data/vendor/rust/rust/namespace.rb +61 -0
  120. data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
  121. data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
  122. data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
  123. data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
  124. data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
  125. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
  126. data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
  127. data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
  128. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +91 -0
  129. data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
  130. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +26 -0
  131. data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
  132. data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
  133. data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
  134. data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
  135. data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
  136. data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
  137. data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
  138. data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
  139. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +7 -0
  140. data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
  141. data/vendor/rust/rust/type.rb +98 -0
  142. data/vendor/rust/test/Makefile +4 -0
  143. data/vendor/rust/test/constants.rb +36 -0
  144. data/vendor/rust/test/cppclass.cc +45 -0
  145. data/vendor/rust/test/cppclass.hh +67 -0
  146. data/vendor/rust/test/cppclass.rb +59 -0
  147. data/vendor/rust/test/cwrapper.c +74 -0
  148. data/vendor/rust/test/cwrapper.h +41 -0
  149. data/vendor/rust/test/cwrapper.rb +56 -0
  150. data/vendor/rust/test/dummyclass.hh +31 -0
  151. data/vendor/rust/test/lib/extension-test.rb +98 -0
  152. data/vendor/rust/test/operators.cc +41 -0
  153. data/vendor/rust/test/operators.hh +39 -0
  154. data/vendor/rust/test/operators.rb +39 -0
  155. data/vendor/rust/test/test-constants.rb +43 -0
  156. data/vendor/rust/test/test-cppclass.rb +82 -0
  157. data/vendor/rust/test/test-cwrapper.rb +80 -0
  158. data/vendor/rust/test/test-operators.rb +42 -0
  159. metadata +293 -0
@@ -0,0 +1,126 @@
1
+ module Gecode::Constraints::IntEnum
2
+ class Expression
3
+ # Initiates a sort constraint. Beyond the common options the sort constraint
4
+ # can also take the following options:
5
+ #
6
+ # [:as] Defines a target (must be an int variable enumerable) that will
7
+ # hold the sorted version of the original enumerable. The original
8
+ # enumerable will not be affected (i.e. will not necessarily be
9
+ # sorted)
10
+ # [:order] Sets an int variable enumerable that should be used to store the
11
+ # order of the original enum's variables when sorted. The original
12
+ # enumerable will not be affected (i.e. will not necessarily be
13
+ # sorted)
14
+ #
15
+ # If neither of those options are specified then the original enumerable
16
+ # will be constrained to be sorted (otherwise not). Sort constraints with
17
+ # options do not allow negation.
18
+ def sorted(options = {})
19
+ # Extract and check options.
20
+ target = options.delete(:as)
21
+ order = options.delete(:order)
22
+ unless target.nil? or target.respond_to? :to_int_var_array
23
+ raise TypeError, 'Expected int var enum as :as, got ' +
24
+ "#{target.class}."
25
+ end
26
+ unless order.nil? or order.respond_to? :to_int_var_array
27
+ raise TypeError, 'Expected int var enum as :order, got ' +
28
+ "#{order.class}."
29
+ end
30
+
31
+ # Extract standard options and convert to constraint.
32
+ @params.update(Gecode::Constraints::Util.decode_options(options))
33
+ if target.nil? and order.nil?
34
+ @model.add_constraint Sort::SortConstraint.new(@model, @params)
35
+ else
36
+ # Do not allow negation.
37
+ if @params[:negate]
38
+ raise Gecode::MissingConstraintError, 'A negated sort with options ' +
39
+ 'is not implemented.'
40
+ end
41
+
42
+ @params.update(:target => target, :order => order)
43
+ @model.add_constraint Sort::SortConstraintWithOptions.new(@model,
44
+ @params)
45
+ end
46
+ end
47
+ end
48
+
49
+ # A module that gathers the classes and modules used in sort constraints.
50
+ module Sort #:nodoc:
51
+ # Describes a sort constraint which constrains a target enumeration of
52
+ # integer variables to be the sorted version of another set of integer
53
+ # variables. Optionally a third enumeration may be used to define the order
54
+ # in which the the variables should be sorted.
55
+ #
56
+ # Neither negation nor reification is supported.
57
+ #
58
+ # == Example
59
+ #
60
+ # # Constrains +sorted_numbers+ to be a sorted version of +numbers+.
61
+ # numbers.must_be.sorted(:as => sorted_numbers)
62
+ #
63
+ # # Constrains +sorted_numbers+ to be +numbers+ sorted in the order
64
+ # # described by the integer variable enumeration +order+.
65
+ # numbers.must_be.sorted(:as => sorted_numbers, :order => order)
66
+ class SortConstraintWithOptions < Gecode::Constraints::Constraint
67
+ def post
68
+ if @params[:target].nil?
69
+ # We must have a target.
70
+ lhs = @params[:lhs]
71
+ @params[:target] = @model.int_var_array(lhs.size, lhs.domain_range)
72
+ end
73
+
74
+ # Prepare the parameters.
75
+ params = @params.values_at(:lhs, :target, :order, :strength).map do |param|
76
+ if param.respond_to? :to_int_var_array
77
+ param.to_int_var_array
78
+ else
79
+ param
80
+ end
81
+ end.delete_if{ |param| param.nil? }
82
+ # Post the constraint.
83
+ Gecode::Raw::sortedness(@model.active_space, *params)
84
+ end
85
+ end
86
+
87
+ # Describes a sort constraint which constrains an enumeration of integer
88
+ # variables to be sorted. Supports reification and negation.
89
+ #
90
+ # == Example
91
+ #
92
+ # # Constrains the variables in +int_enum+ to be sorted ascendingly.
93
+ # int_enum.must_be.sorted
94
+ #
95
+ # # Reifies the constraint that the variables in +int_enum+ to be sorted
96
+ # # ascendingly with the boolean variable +is_sorted+, while selecting
97
+ # # +domain+ as strength.
98
+ # int_enum.must_be.sorted(:reify => :is_sorted, :strength => :domain)
99
+ class SortConstraint < Gecode::Constraints::ReifiableConstraint
100
+ def post
101
+ lhs, strength, reif_var = @params.values_at(:lhs, :strength, :reif)
102
+ using_reification = !reif_var.nil?
103
+
104
+ # We translate the constraint into n-1 relation constraints.
105
+ options = {:strength =>
106
+ Gecode::Constraints::Util::PROPAGATION_STRENGTHS.invert[strength]}
107
+ if using_reification
108
+ reification_variables = @model.bool_var_array(lhs.size - 1)
109
+ end
110
+ (lhs.size - 1).times do |i|
111
+ first, second = lhs[i, 2]
112
+ rel_options = options.clone
113
+ if using_reification
114
+ # Reify each relation constraint and then bind them all together.
115
+ rel_options[:reify] = reification_variables[i]
116
+ end
117
+ first.must_be.less_than_or_equal_to(second, rel_options)
118
+ end
119
+ if using_reification
120
+ reification_variables.conjunction.must == reif_var
121
+ end
122
+ end
123
+ negate_using_reification
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,37 @@
1
+ module Gecode
2
+ module IntEnumMethods
3
+ include Gecode::Constraints::LeftHandSideMethods
4
+
5
+ private
6
+
7
+ # Produces an expression for the lhs module.
8
+ def expression(params)
9
+ params.update(:lhs => self)
10
+ Constraints::IntEnum::Expression.new(@model, params)
11
+ end
12
+ end
13
+
14
+ # A module containing constraints that have enumerations of integer
15
+ # variables as left hand side.
16
+ module Constraints::IntEnum
17
+ # Expressions with int enums as left hand sides.
18
+ class Expression < Gecode::Constraints::Expression #:nodoc:
19
+ # Raises TypeError unless the left hand side is an int enum.
20
+ def initialize(model, params)
21
+ super
22
+
23
+ unless params[:lhs].respond_to? :to_int_var_array
24
+ raise TypeError, 'Must have int enum as left hand side.'
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ require 'gecoder/interface/constraints/int_enum/distinct'
32
+ require 'gecoder/interface/constraints/int_enum/equality'
33
+ require 'gecoder/interface/constraints/int_enum/channel'
34
+ require 'gecoder/interface/constraints/int_enum/element'
35
+ require 'gecoder/interface/constraints/int_enum/count'
36
+ require 'gecoder/interface/constraints/int_enum/sort'
37
+ require 'gecoder/interface/constraints/int_enum/arithmetic'
@@ -0,0 +1,58 @@
1
+ module Gecode
2
+ class FreeIntVar
3
+ include Gecode::Constraints::LeftHandSideMethods
4
+
5
+ private
6
+
7
+ # Produces an expression for the lhs module.
8
+ def expression(params)
9
+ params.update(:lhs => self)
10
+ Constraints::Int::Expression.new(@model, params)
11
+ end
12
+ end
13
+
14
+ # A module containing constraints that have int variables as left hand side
15
+ # (but not enumerations).
16
+ module Constraints::Int
17
+ # Describes an integer expression.
18
+ class Expression < Gecode::Constraints::Expression #:nodoc:
19
+ end
20
+
21
+ # A composite expression which is an int expression with a left hand side
22
+ # resulting from a previous constraint.
23
+ class CompositeExpression < Gecode::Constraints::CompositeExpression #:nodoc:
24
+ # The block given should take three parameters. The first is the variable
25
+ # that should be the left hand side, if it's nil then a new one should be
26
+ # created. The second is the has of parameters. The block should return
27
+ # the variable used as left hand side.
28
+ def initialize(model, params, &block)
29
+ super(Expression, Gecode::FreeIntVar, lambda{ model.int_var }, model,
30
+ params, &block)
31
+ end
32
+ end
33
+
34
+ # Describes a stub that produces an int variable, which can then be used
35
+ # with the normal int variable constraints. An example would be the element
36
+ # constraint.
37
+ #
38
+ # int_enum[int_var].must > rhs
39
+ #
40
+ # <tt>int_enum[int_var]</tt> produces an int variable which the constraint
41
+ # <tt>.must > rhs</tt> is then applied to. In the above case two
42
+ # constraints (and one temporary variable) are required, but in the case of
43
+ # equality only one constraint is required.
44
+ #
45
+ # Whether a constraint involving a reification stub supports negation,
46
+ # reification, strength options and so on depends on the constraint on the
47
+ # right hand side.
48
+ class CompositeStub < Gecode::Constraints::CompositeStub
49
+ def initialize(model, params)
50
+ super(CompositeExpression, model, params)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ require 'gecoder/interface/constraints/int/linear'
57
+ require 'gecoder/interface/constraints/int/domain'
58
+ require 'gecoder/interface/constraints/int/arithmetic'
@@ -0,0 +1,78 @@
1
+ module Gecode::Constraints
2
+ # Base class for all reifiable constraints.
3
+ class ReifiableConstraint < Constraint
4
+ # Gets the reification variable of the constraint, nil if none exists.
5
+ def reification_var
6
+ @params[:reif]
7
+ end
8
+
9
+ # Sets the reification variable of the constraint, nil if none should be
10
+ # used.
11
+ def reification_var=(new_var)
12
+ @params[:reif] = new_var
13
+ end
14
+
15
+ # Produces a disjunction of two reifiable constraints, producing a new
16
+ # reifiable constraint.
17
+ def |(constraint)
18
+ with_reification_variables(constraint) do |b1, b2|
19
+ # Create the disjunction constraint.
20
+ (b1 | b2).must_be.true
21
+ end
22
+ end
23
+
24
+ # Produces a conjunction of two reifiable constraints, producing a new
25
+ # reifiable constraint.
26
+ def &(constraint)
27
+ with_reification_variables(constraint) do |b1, b2|
28
+ # Create the conjunction constraint.
29
+ (b1 & b2).must_be.true
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ # Yields two boolean variables to the specified block. The first one is
36
+ # self's reification variable and the second one is the reification variable
37
+ # of the specified constraint. Reuses reification variables if possible,
38
+ # otherwise creates new ones.
39
+ def with_reification_variables(constraint, &block)
40
+ raise TypeError unless constraint.kind_of? ReifiableConstraint
41
+
42
+ # Set up the reification variables, using existing variables if they
43
+ # exist.
44
+ con1_holds = self.reification_var
45
+ con2_holds = constraint.reification_var
46
+ if con1_holds.nil?
47
+ con1_holds = @model.bool_var
48
+ self.reification_var = con1_holds
49
+ end
50
+ if con2_holds.nil?
51
+ con2_holds = @model.bool_var
52
+ constraint.reification_var = con2_holds
53
+ end
54
+ yield(con1_holds, con2_holds)
55
+ end
56
+
57
+ # If called the negation of the constraint will be handled using the
58
+ # reification variable. This means that the post method (which has to be
59
+ # defined prior to calling this method) doesn't have to bother about
60
+ # negation.
61
+ def self.negate_using_reification
62
+ class_eval do
63
+ alias_method :post_without_negation, :post
64
+
65
+ def post
66
+ if @params[:negate]
67
+ if @params[:reif].nil?
68
+ # Create a reification variable if none exists.
69
+ @params[:reif] = @model.bool_var
70
+ end
71
+ @params[:reif].must_be.false
72
+ end
73
+ post_without_negation
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,75 @@
1
+ module Gecode
2
+ class FreeSetVar
3
+ # Starts a constraint on the size of the set.
4
+ def size
5
+ params = {:lhs => self}
6
+ Gecode::Constraints::Set::Cardinality::SizeExpressionStub.new(
7
+ @model, params)
8
+ end
9
+ end
10
+ end
11
+
12
+ module Gecode::Constraints::Set
13
+ # A module that gathers the classes and modules used in cardinality
14
+ # constraints.
15
+ module Cardinality #:nodoc:
16
+ # Describes a cardinality constraint specifically for ranges. This is just
17
+ # a special case which is used instead of the more general composite
18
+ # constraint when the target cardinality is a range.
19
+ class CardinalityConstraint < Gecode::Constraints::Constraint #:nodoc:
20
+ def post
21
+ var, range = @params.values_at(:lhs, :range)
22
+ Gecode::Raw::cardinality(@model.active_space, var.bind, range.first,
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)
31
+ end
32
+ end
33
+
34
+ # Describes a cardinality expression started with set.size.must .
35
+ class Expression < Gecode::Constraints::Int::CompositeExpression #:nodoc:
36
+ def in(range)
37
+ if range.kind_of?(Range) and !@params[:negate]
38
+ @params.update(:range => range)
39
+ @model.add_constraint CardinalityConstraint.new(@model, @params)
40
+ else
41
+ super(range)
42
+ end
43
+ end
44
+ end
45
+
46
+ # Describes a CompositeStub for the cardianlity constraint which constrains
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]
67
+ if constrain
68
+ variable.must_be.in lhs.lower_bound.size..lhs.upper_bound.size
69
+ end
70
+
71
+ Gecode::Raw::cardinality(@model.active_space, lhs.bind, variable.bind)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,193 @@
1
+ module Gecode
2
+ class FreeSetVar
3
+ # Starts a constraint on the minimum value of the set.
4
+ def min
5
+ params = {:lhs => self}
6
+ Gecode::Constraints::Set::Connection::MinExpressionStub.new(@model, params)
7
+ end
8
+
9
+ # Starts a constraint on the maximum value of the set.
10
+ def max
11
+ params = {:lhs => self}
12
+ Gecode::Constraints::Set::Connection::MaxExpressionStub.new(@model, params)
13
+ end
14
+
15
+ # Starts a constraint on the sum of the set. The option :weights may
16
+ # optionally be given with a hash of weights as value. If it is then the
17
+ # weighted sum, using the hash as weight function, will be constrained. The
18
+ # option :substitutions may also be given (with a hash as value), if it is
19
+ # then the sum of the set with all elements replaced according to the hash
20
+ # is constrained. Elements mapped to nil by the weights or substitutions
21
+ # hash are removed from the upper bound of the set. Only one of the two
22
+ # options may be given at the same time.
23
+ def sum(options = {:weights => weights = Hash.new(1)})
24
+ if options.empty? or options.keys.size > 1
25
+ raise ArgumentError, 'One of the options :weights and :substitutions, ' +
26
+ 'or neither, must be specified.'
27
+ end
28
+ params = {:lhs => self}
29
+ unless options.empty?
30
+ case options.keys.first
31
+ when :substitutions: params.update(options)
32
+ when :weights:
33
+ weights = options[:weights]
34
+ substitutions = Hash.new do |hash, key|
35
+ if weights[key].nil?
36
+ hash[key] = nil
37
+ else
38
+ hash[key] = key * weights[key]
39
+ end
40
+ end
41
+ params.update(:substitutions => substitutions)
42
+ else raise ArgumentError, "Unrecognized option #{options.keys.first}."
43
+ end
44
+ end
45
+ Gecode::Constraints::Set::Connection::SumExpressionStub.new(@model, params)
46
+ end
47
+ end
48
+ end
49
+
50
+ module Gecode::Constraints::Set
51
+ class Expression
52
+ # Adds a constraint that forces specified values to be included in the
53
+ # set. This constraint has the side effect of sorting the variables in
54
+ # non-descending order.
55
+ def include(variables)
56
+ unless variables.respond_to? :to_int_var_array
57
+ raise TypeError, "Expected int var enum, got #{variables.class}."
58
+ end
59
+ if @params[:negate]
60
+ raise Gecode::MissingConstraintError, 'A negated include is not ' +
61
+ 'implemented.'
62
+ end
63
+
64
+ @params.update(:variables => variables)
65
+ @model.add_constraint Connection::IncludeConstraint.new(@model, @params)
66
+ end
67
+ end
68
+
69
+ # A module that gathers the classes and modules used in connection
70
+ # constraints.
71
+ module Connection #:nodoc:
72
+ # Describes a CompositeStub for the min constraint which constrains the
73
+ # minimum value of a set variable.
74
+ #
75
+ # == Examples
76
+ #
77
+ # # Constrains the minimum value of +set+ to be larger than 17.
78
+ # set.min.must > 17
79
+ #
80
+ # # Constrains the minimum value of +set+ to equal the integer variable
81
+ # # +min+.
82
+ # set.min.must == min
83
+ #
84
+ # # Constrains the minimum value of +set+ to not be larger than the
85
+ # # integer variable +ceil+.
86
+ # set.min.must_not > ceil
87
+ #
88
+ # # The same as above but reified with the boolean variable
89
+ # # +is_not_above_ceiling+ and with the strength +domain+ applied.
90
+ # set.min.must_not_be.larger_than(ceil, :reify => :is_not_above_ceiling,
91
+ # :strength => :domain)
92
+ class MinExpressionStub < Gecode::Constraints::Int::CompositeStub
93
+ def constrain_equal(variable, params, constrain)
94
+ set = params[:lhs]
95
+ if constrain
96
+ variable.must_be.in set.upper_bound.min..set.lower_bound.min
97
+ end
98
+
99
+ Gecode::Raw::min(@model.active_space, set.bind, variable.bind)
100
+ end
101
+ end
102
+
103
+ # Describes a CompositeStub for the max constraint which constrains the
104
+ # maximum value of a set variable.
105
+ #
106
+ # == Examples
107
+ #
108
+ # # Constrains the maximum value of +set+ to be larger than 17.
109
+ # set.max.must > 17
110
+ #
111
+ # # Constrains the maximum value of +set+ to equal the integer variable
112
+ # # +max+.
113
+ # set.max.must == max
114
+ #
115
+ # # Constrains the maximum value of +set+ to not be less than the
116
+ # # integer variable +floor+.
117
+ # set.max.must_not < floor
118
+ #
119
+ # # The same as above but reified with the boolean variable
120
+ # # +is_not_below_floor+ and with the strength +domain+ applied.
121
+ # set.max.must_not_be.less_than(ceil, :reify => :is_not_below_floor,
122
+ # :strength => :domain)
123
+ class MaxExpressionStub < Gecode::Constraints::Int::CompositeStub
124
+ def constrain_equal(variable, params, constrain)
125
+ set = params[:lhs]
126
+ if constrain
127
+ variable.must_be.in set.lower_bound.max..set.upper_bound.max
128
+ end
129
+
130
+ Gecode::Raw::max(@model.active_space, set.bind, variable.bind)
131
+ end
132
+ end
133
+
134
+ # Describes a CompositeStub for the sum constraint which constrains the
135
+ # sum of all values in a set variable.
136
+ #
137
+ # == Examples
138
+ #
139
+ # # Constrains the sum of all values in +set+ to be larger than 17.
140
+ # set.sum.must > 17
141
+ #
142
+ # # Constrains the sum of all values in +set+ to equal the integer
143
+ # # variable +sum+.
144
+ # set.sum.must == sum
145
+ #
146
+ # # Constrains the sum of all values in +set+ to not be larger than the
147
+ # # integer variable +resources+.
148
+ # set.sum.must_not > resources
149
+ #
150
+ # # The same as above but reified with the boolean variable
151
+ # # +not_over_budget+ and with the strength +domain+ applied.
152
+ # set.sum.must_not_be.larger_than(resources, :reify => :not_over_budget,
153
+ # :strength => :domain)
154
+ class SumExpressionStub < Gecode::Constraints::Int::CompositeStub
155
+ def constrain_equal(variable, params, constrain)
156
+ set, subs = params.values_at(:lhs, :substitutions)
157
+ lub = set.upper_bound.to_a
158
+ lub.delete_if{ |e| subs[e].nil? }
159
+ substituted_lub = lub.map{ |e| subs[e] }
160
+ if constrain
161
+ # Compute the theoretical bounds of the weighted sum. This is slightly
162
+ # sloppy since we could also use the contents of the greatest lower
163
+ # bound.
164
+ min = substituted_lub.find_all{ |e| e < 0}.inject(0){ |x, y| x + y }
165
+ max = substituted_lub.find_all{ |e| e > 0}.inject(0){ |x, y| x + y }
166
+ variable.must_be.in min..max
167
+ end
168
+
169
+ Gecode::Raw::weights(@model.active_space, lub, substituted_lub,
170
+ set.bind, variable.bind)
171
+ end
172
+ end
173
+
174
+ # Describes an include constraint, which constrains the set to include the
175
+ # values of the specified enumeration of integer variables.
176
+ #
177
+ # The constraint has the side effect of sorting the integer variables in a
178
+ # non-descending order. It does not support reification nor negation.
179
+ #
180
+ # == Examples
181
+ #
182
+ # # Constrain +set+ to include the values of all variables in
183
+ # # +int_enum+.
184
+ # set.must.include int_enum
185
+ class IncludeConstraint < Gecode::Constraints::Constraint
186
+ def post
187
+ set, variables = @params.values_at(:lhs, :variables)
188
+ Gecode::Raw::match(@model.active_space, set.bind,
189
+ variables.to_int_var_array)
190
+ end
191
+ end
192
+ end
193
+ end