gecoder-with-gecode 0.8.1-mswin32 → 0.8.2-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.
data/CHANGES CHANGED
@@ -1,3 +1,13 @@
1
+ == Version 0.8.2
2
+ This release adds search statistics along with some new arithmetic constraints
3
+ and channel constraints between boolean and integer variables.
4
+
5
+ * Wrapping an enumerable that is already wrapped is no longer allowed.
6
+ * Added search statistics.
7
+ * Added squared value and square root constraints.
8
+ * Added channel constraints between single integer variables and boolean variables.
9
+ * Added channel constraints between enumerations of boolean variables and single integer variables.
10
+
1
11
  == Version 0.8.1
2
12
  This release adds tuple constraints along with a couple of minor features. It
3
13
  also fixes a bug introduced in the previous version.
Binary file
@@ -908,6 +908,22 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
908
908
  func.add_parameter "Gecode::PropKind", "pk"
909
909
  end
910
910
 
911
+ ns.add_function "sqr" do |func|
912
+ func.add_parameter "Gecode::MSpace *", "home"
913
+ func.add_parameter "Gecode::IntVar", "x0"
914
+ func.add_parameter "Gecode::IntVar", "x1"
915
+ func.add_parameter "Gecode::IntConLevel", "icl"
916
+ func.add_parameter "Gecode::PropKind", "pk"
917
+ end
918
+
919
+ ns.add_function "sqrt" do |func|
920
+ func.add_parameter "Gecode::MSpace *", "home"
921
+ func.add_parameter "Gecode::IntVar", "x0"
922
+ func.add_parameter "Gecode::IntVar", "x1"
923
+ func.add_parameter "Gecode::IntConLevel", "icl"
924
+ func.add_parameter "Gecode::PropKind", "pk"
925
+ end
926
+
911
927
  ns.add_function "branch" do |func|
912
928
  func.add_parameter "Gecode::MSpace *", "home"
913
929
  func.add_parameter "Gecode::MIntVarArray *", "iva" do |param|
@@ -955,6 +971,25 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
955
971
  func.add_parameter "Gecode::PropKind", "pk"
956
972
  end
957
973
 
974
+ ns.add_function "channel" do |func|
975
+ func.add_parameter "Gecode::MSpace*", "home"
976
+ func.add_parameter "Gecode::IntVar", "x0"
977
+ func.add_parameter "Gecode::BoolVar", "x1"
978
+ func.add_parameter "Gecode::IntConLevel", "icl"
979
+ func.add_parameter "Gecode::PropKind", "pk"
980
+ end
981
+
982
+ ns.add_function "channel" do |func|
983
+ func.add_parameter "Gecode::MSpace*", "home"
984
+ func.add_parameter "Gecode::MBoolVarArray *", "x" do |param|
985
+ param.custom_conversion = "*ruby2Gecode_MBoolVarArrayPtr(argv[1], 2)->ptr()"
986
+ end
987
+ func.add_parameter "Gecode::IntVar", "y"
988
+ func.add_parameter "int", "o"
989
+ func.add_parameter "Gecode::IntConLevel", "icl"
990
+ func.add_parameter "Gecode::PropKind", "pk"
991
+ end
992
+
958
993
  ns.add_function "count" do |func|
959
994
  func.add_parameter "Gecode::MSpace*", "home"
960
995
  func.add_parameter "Gecode::MIntVarArray *", "x" do |param|
@@ -217,6 +217,40 @@ module Gecode
217
217
  end
218
218
  end
219
219
 
220
+ # A module that contains utility-methods for extensional constraints.
221
+ module Util::Extensional #:nodoc:
222
+ module_function
223
+
224
+ # Checks that the specified enumeration is an enumeration containing
225
+ # one or more tuples of the specified size. It also allows the caller
226
+ # to define additional tests by providing a block, which is given each
227
+ # tuple. If a test fails then an appropriate error is raised.
228
+ def perform_tuple_checks(tuples, expected_size, &additional_test)
229
+ unless tuples.respond_to?(:each)
230
+ raise TypeError, 'Expected an enumeration with tuples, got ' +
231
+ "#{tuples.class}."
232
+ end
233
+
234
+ if tuples.empty?
235
+ raise ArgumentError, 'One or more tuples must be specified.'
236
+ end
237
+
238
+ tuples.each do |tuple|
239
+ unless tuple.respond_to?(:each)
240
+ raise TypeError, 'Expected an enumeration containing enumeraions, ' +
241
+ "got #{tuple.class}."
242
+ end
243
+
244
+ unless tuple.size == expected_size
245
+ raise ArgumentError, 'All tuples must be of the same size as the ' +
246
+ 'number of variables in the array.'
247
+ end
248
+
249
+ yield tuple
250
+ end
251
+ end
252
+ end
253
+
220
254
  # Describes a constraint expressions. An expression is produced by calling
221
255
  # some form of must on a left hand side. The expression waits for a right
222
256
  # hand side so that it can post the corresponding constraint.
@@ -26,6 +26,13 @@ module Gecode
26
26
  # Describes a boolean expression (following after must*).
27
27
  class Expression #:nodoc:
28
28
  def ==(expression, options = {})
29
+ unless expression.kind_of?(ExpressionTree) or
30
+ expression.kind_of?(Gecode::FreeBoolVar) or
31
+ expression.kind_of?(TrueClass) or expression.kind_of?(FalseClass) or
32
+ expression.respond_to?(:to_minimodel_lin_exp)
33
+ raise TypeError, 'Invalid right hand side of boolean equation.'
34
+ end
35
+
29
36
  @params.update Gecode::Constraints::Util.decode_options(options)
30
37
  @model.add_constraint BooleanConstraint.new(@model,
31
38
  @params.update(:rhs => expression))
@@ -0,0 +1,23 @@
1
+ module Gecode::Constraints::Bool
2
+ class Expression
3
+ alias_method :pre_channel_equals, :==
4
+
5
+ # Constrains the boolean variable to be equal to the specified integer
6
+ # variable.
7
+ def ==(int, options = {})
8
+ unless @params[:lhs].kind_of?(Gecode::FreeBoolVar) and
9
+ int.kind_of?(Gecode::FreeIntVar)
10
+ return pre_channel_equals(int, options)
11
+ end
12
+
13
+ # Provide commutivity to the corresponding int variable constraint.
14
+ if @params[:negate]
15
+ int.must_not.equal(@params[:lhs], options)
16
+ else
17
+ int.must.equal(@params[:lhs], options)
18
+ end
19
+ end
20
+
21
+ alias_comparison_methods
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ module Gecode::Constraints::BoolEnum
2
+ class Expression
3
+ # Adds a channel constraint on the variables in the enum with the specified
4
+ # integer variable. Beyond the common options the channel constraint can
5
+ # also take the following option:
6
+ #
7
+ # [:offset] Specifies an offset for the integer variable. If the offset is
8
+ # set to k then the integer variable takes value i+k exactly
9
+ # when the variable at index i in the boolean enumration is true
10
+ # and the rest are false.
11
+ def channel(int_var, options = {})
12
+ if @params[:negate]
13
+ raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
14
+ 'is not implemented.'
15
+ end
16
+ if options.has_key? :reify
17
+ raise ArgumentError, 'The channel constraint does not support the ' +
18
+ 'reification option.'
19
+ end
20
+ unless int_var.kind_of? Gecode::FreeIntVar
21
+ raise TypeError, "Expected an integer variable, got #{int_var.class}."
22
+ end
23
+
24
+ @params.update(:rhs => int_var, :offset => options.delete(:offset) || 0)
25
+ @params.update(Gecode::Constraints::Util.decode_options(options))
26
+ @model.add_constraint Channel::ChannelConstraint.new(@model, @params)
27
+ end
28
+ end
29
+
30
+ # A module that gathers the classes and modules used in channel constraints
31
+ # involving one boolean enum and one integer variable.
32
+ module Channel #:nodoc:
33
+ # Describes a channel constraint that "channels" an enumerations of
34
+ # boolean variables with an integer variable. This constrains the integer
35
+ # variable to take value i exactly when the variable at index i in the
36
+ # boolean enumeration is true and the others are false.
37
+ #
38
+ # Neither reification nor negation is supported.
39
+ #
40
+ # == Examples
41
+ #
42
+ # # Constrains the enumeration called +selected_option+ to be false in the
43
+ # # first four positions and have exactly one true variable in the other.
44
+ # selected_option.must.channel selected_option_index
45
+ # selected_option_index.must_be > 3
46
+ #
47
+ # # Constrains the enumeration called +selected_option+ to be false in the
48
+ # # first five positions and have exactly one true variable in the other.
49
+ # selected_option.must.channel(selected_option_index, :offset => 1)
50
+ # selected_option_index.must_be > 3
51
+ class ChannelConstraint < Gecode::Constraints::Constraint
52
+ def post
53
+ lhs, rhs, offset = @params.values_at(:lhs, :rhs, :offset)
54
+ Gecode::Raw::channel(@model.active_space, lhs.to_bool_var_array,
55
+ rhs.bind, offset, *propagation_options)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -10,16 +10,17 @@ module Gecode::Constraints::BoolEnum
10
10
  raise ArgumentError, 'Reification is not supported by the tuple ' +
11
11
  'constraint.'
12
12
  end
13
- unless tuples.respond_to?(:each) and
14
- tuples.all?{ |tuple| tuple.respond_to?(:each) }
15
- raise TypeError, 'Expected an enumeration with tuples, got ' +
16
- "#{tuples.class}."
17
- end
18
- unless tuples.all?{ |tuple|
19
- tuple.all?{ |x| x.kind_of?(TrueClass) or x.kind_of?(FalseClass) }}
20
- raise TypeError, 'All tuples must contain booleans.'
13
+
14
+ util = Gecode::Constraints::Util
15
+
16
+ # Check that the tuples are correct.
17
+ expected_size = @params[:lhs].size
18
+ util::Extensional.perform_tuple_checks(tuples, expected_size) do |tuple|
19
+ unless tuple.all?{ |x| x.kind_of?(TrueClass) or x.kind_of?(FalseClass) }
20
+ raise TypeError, 'All tuples must contain booleans.'
21
+ end
21
22
  end
22
-
23
+
23
24
  @params[:tuples] = tuples
24
25
  @model.add_constraint Extensional::TupleConstraint.new(@model,
25
26
  @params.update(Gecode::Constraints::Util.decode_options(options)))
@@ -30,3 +30,4 @@ end
30
30
 
31
31
  require 'gecoder/interface/constraints/bool_enum/relation'
32
32
  require 'gecoder/interface/constraints/bool_enum/extensional'
33
+ require 'gecoder/interface/constraints/bool_enum/channel'
@@ -73,3 +73,4 @@ end
73
73
 
74
74
  require 'gecoder/interface/constraints/bool/boolean'
75
75
  require 'gecoder/interface/constraints/bool/linear'
76
+ require 'gecoder/interface/constraints/bool/channel'
@@ -4,6 +4,20 @@ class Gecode::FreeIntVar
4
4
  Gecode::Constraints::Int::Arithmetic::AbsExpressionStub.new(@model,
5
5
  :lhs => self)
6
6
  end
7
+
8
+ # Initiates an arithmetic squared value constraint.
9
+ def squared
10
+ Gecode::Constraints::Int::Arithmetic::SquaredExpressionStub.new(@model,
11
+ :lhs => self)
12
+ end
13
+
14
+ # Initiates an arithmetic squared root constraint.
15
+ def sqrt
16
+ Gecode::Constraints::Int::Arithmetic::SquareRootExpressionStub.new(@model,
17
+ :lhs => self)
18
+ end
19
+ alias_method :square_root, :sqrt
20
+
7
21
 
8
22
  alias_method :pre_arith_mult, :* if instance_methods.include? '*'
9
23
 
@@ -52,7 +66,7 @@ module Gecode::Constraints::Int::Arithmetic #:nodoc:
52
66
  # # The value of +x*y+ must be equal to their sum.
53
67
  # (x*y).must == x + y
54
68
  #
55
- # # The valye of +x*y+ must be less than 17, with +bool+ as reification
69
+ # # The value of +x*y+ must be less than 17, with +bool+ as reification
56
70
  # # variable and +domain+ as strength.
57
71
  # (x*y).must_be.less_than(17, :reify => bool, :strength => :domain)
58
72
  class MultExpressionStub < Gecode::Constraints::Int::CompositeStub
@@ -69,4 +83,67 @@ module Gecode::Constraints::Int::Arithmetic #:nodoc:
69
83
  variable.bind, *propagation_options)
70
84
  end
71
85
  end
86
+
87
+ # Describes a CompositeStub for the squared constraint, which constrain
88
+ # the squared value of the variable.
89
+ #
90
+ # == Examples
91
+ #
92
+ # # The value of +x*x+ must be equal to y.
93
+ # x.squared.must == y
94
+ #
95
+ # # The value of +x*x+ must be less than or equal to 16, with +bool+ as
96
+ # # reification variable and +domain+ as strength.
97
+ # x.squared.must_be.less_or_equal(16, :reify => bool, :strength => :domain)
98
+ class SquaredExpressionStub < Gecode::Constraints::Int::CompositeStub
99
+ def constrain_equal(variable, params, constrain)
100
+ lhs = @params[:lhs]
101
+ if constrain
102
+ min = lhs.min; max = lhs.max
103
+ products = [min*max, min*min, max*max]
104
+ variable.must_be.in products.min..products.max
105
+ end
106
+
107
+ Gecode::Raw::sqr(@model.active_space, lhs.bind, variable.bind,
108
+ *propagation_options)
109
+ end
110
+ end
111
+
112
+ # Describes a CompositeStub for the square root constraint, which constrain
113
+ # the rounded down square root of the variable.
114
+ #
115
+ # == Examples
116
+ #
117
+ # # The square root of +x+, rounded down, must equal y.
118
+ # x.square_root.must == y
119
+ #
120
+ # # The square root of +x+, rounded down, must be larger than 17, with
121
+ # # +bool+ as reification variable and +domain+ as strength.
122
+ # x.square_root.must_be.larger_than(17, :reify => bool, :strength => :domain)
123
+ class SquareRootExpressionStub < Gecode::Constraints::Int::CompositeStub
124
+ def constrain_equal(variable, params, constrain)
125
+ lhs = @params[:lhs]
126
+ if constrain
127
+ max = lhs.max
128
+ if max < 0
129
+ # The left hand side does not have a real valued square root.
130
+ upper_bound = 0
131
+ else
132
+ upper_bound = Math.sqrt(max).floor;
133
+ end
134
+
135
+ min = lhs.min
136
+ if min < 0
137
+ lower_bound = 0
138
+ else
139
+ lower_bound = Math.sqrt(min).floor;
140
+ end
141
+
142
+ variable.must_be.in lower_bound..upper_bound
143
+ end
144
+
145
+ Gecode::Raw::sqrt(@model.active_space, lhs.bind, variable.bind,
146
+ *propagation_options)
147
+ end
148
+ end
72
149
  end
@@ -0,0 +1,73 @@
1
+ module Gecode::Constraints::Int
2
+ class Expression
3
+ alias_method :pre_channel_equals, :==
4
+
5
+ # Constrains the integer variable to be equal to the specified boolean
6
+ # variable. I.e. constrains the integer variable to be 1 when the boolean
7
+ # variable is true and 0 if the boolean variable is false.
8
+ def ==(bool, options = {})
9
+ unless @params[:lhs].kind_of?(Gecode::FreeIntVar) and
10
+ bool.kind_of?(Gecode::FreeBoolVar)
11
+ return pre_channel_equals(bool, options)
12
+ end
13
+
14
+ if @params[:negate]
15
+ raise Gecode::MissingConstraintError, 'A negated channel constraint ' +
16
+ 'is not implemented.'
17
+ end
18
+ unless options[:reify].nil?
19
+ raise ArgumentError, 'Reification is not supported by the channel ' +
20
+ 'constraint.'
21
+ end
22
+
23
+ @params.update(Gecode::Constraints::Util.decode_options(options))
24
+ @params[:rhs] = bool
25
+ @model.add_constraint Channel::ChannelConstraint.new(@model, @params)
26
+ end
27
+
28
+ alias_comparison_methods
29
+
30
+ # Adds a channel constraint on the integer variable and the variables in
31
+ # the specifed enum of boolean variables. Beyond the common options the
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
+ def channel(bool_enum, options = {})
39
+ unless bool_enum.respond_to? :to_bool_var_array
40
+ raise TypeError, 'Expected an enumration of boolean variables, got ' +
41
+ "#{bool_enum.class}."
42
+ end
43
+
44
+ # Just provide commutivity with the boolean enum channel constraint.
45
+ if @params[:negate]
46
+ bool_enum.must_not.channel(@params[:lhs], options)
47
+ else
48
+ bool_enum.must.channel(@params[:lhs], options)
49
+ end
50
+ end
51
+ end
52
+
53
+ # A module that gathers the classes and modules used in channel constraints
54
+ # involving a single integer variable.
55
+ module Channel #:nodoc:
56
+ # Describes a channel constraint that constrains an integer variable to be
57
+ # 1 if a boolean variable is true, and 0 when the boolean variable is false.
58
+ # Does not support negation nor reification.
59
+ #
60
+ # == Examples
61
+ #
62
+ # # The integer variable +x+ must be one exactly when the boolean
63
+ # # variable +bool+ is true.
64
+ # x.must == bool
65
+ class ChannelConstraint < Gecode::Constraints::Constraint
66
+ def post
67
+ lhs, rhs = @params.values_at(:lhs, :rhs)
68
+ Gecode::Raw::channel(@model.active_space, lhs.bind, rhs.bind,
69
+ *propagation_options)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -11,8 +11,16 @@ module Gecode::Constraints::IntEnum
11
11
  enum.respond_to?(:to_set_var_array)
12
12
  raise TypeError, "Expected int or set enum, got #{enum.class}."
13
13
  end
14
+ if enum.respond_to? :to_set_var_array
15
+ if options.has_key? :reify
16
+ raise ArgumentError, 'The channel constraints does not support the ' +
17
+ 'reification option.'
18
+ end
19
+ @params.update(Gecode::Constraints::Set::Util.decode_options(options))
20
+ else
21
+ @params.update(Gecode::Constraints::Util.decode_options(options))
22
+ end
14
23
 
15
- @params.update(Gecode::Constraints::Util.decode_options(options))
16
24
  @params.update(:rhs => enum)
17
25
  @model.add_constraint Channel::ChannelConstraint.new(@model, @params)
18
26
  end
@@ -91,7 +99,7 @@ module Gecode::Constraints::IntEnum
91
99
  Gecode::Raw::channel(@model.active_space, lhs, rhs.to_int_var_array,
92
100
  *propagation_options)
93
101
  else
94
- # Set var array, no strength.
102
+ # Set var array, no propagation options.
95
103
  Gecode::Raw::channel(@model.active_space, lhs, rhs.to_set_var_array)
96
104
  end
97
105
  end
@@ -1,6 +1,7 @@
1
1
  module Gecode::Constraints::IntEnum
2
2
  class Expression
3
- # Posts an equality constraint on the variables in the enum.
3
+ # Posts a tuple constraint on the variables in the enum, constraining them
4
+ # to equal one of the specified tuples.
4
5
  def in(tuples, options = {})
5
6
  if @params[:negate]
6
7
  raise Gecode::MissingConstraintError, 'A negated tuple constraint is ' +
@@ -10,18 +11,20 @@ module Gecode::Constraints::IntEnum
10
11
  raise ArgumentError, 'Reification is not supported by the tuple ' +
11
12
  'constraint.'
12
13
  end
13
- unless tuples.respond_to?(:each) and
14
- tuples.all?{ |tuple| tuple.respond_to?(:each) }
15
- raise TypeError, 'Expected an enumeration with tuples, got ' +
16
- "#{tuples.class}."
17
- end
18
- unless tuples.all?{ |tuple| tuple.all?{ |x| x.kind_of? Fixnum }}
19
- raise TypeError, 'All tuples must contain Fixnum.'
14
+
15
+ util = Gecode::Constraints::Util
16
+
17
+ # Check that the tuples are correct.
18
+ expected_size = @params[:lhs].size
19
+ util::Extensional.perform_tuple_checks(tuples, expected_size) do |tuple|
20
+ unless tuple.all?{ |x| x.kind_of? Fixnum }
21
+ raise TypeError, 'All tuples must contain Fixnum.'
22
+ end
20
23
  end
21
24
 
22
25
  @params[:tuples] = tuples
23
26
  @model.add_constraint Extensional::TupleConstraint.new(@model,
24
- @params.update(Gecode::Constraints::Util.decode_options(options)))
27
+ @params.update(util.decode_options(options)))
25
28
  end
26
29
  end
27
30