lib/gecoder/interface/constraints/set/connection.rb in gecoder-0.8.3 vs lib/gecoder/interface/constraints/set/connection.rb in gecoder-0.9.0
- old
+ new
@@ -1,193 +1,130 @@
-module Gecode
- class FreeSetVar
- # Starts a constraint on the minimum value of the set.
+module Gecode::Set
+ module SetOperand
+ # Produces an IntOperand representing the minimum of the set.
+ #
+ # ==== Examples
+ #
+ # # The minimum of +set+.
+ # set.min
def min
- params = {:lhs => self}
- Gecode::Constraints::Set::Connection::MinExpressionStub.new(@model, params)
+ Connection::SetMinOperand.new(@model, self)
end
- # Starts a constraint on the maximum value of the set.
+ # Produces an IntOperand representing the maximum of the set.
+ #
+ # ==== Examples
+ #
+ # # The maximum of +set+.
+ # set.max
def max
- params = {:lhs => self}
- Gecode::Constraints::Set::Connection::MaxExpressionStub.new(@model, params)
+ Connection::SetMaxOperand.new(@model, self)
end
- # Starts a constraint on the sum of the set. The option :weights may
- # optionally be given with a hash of weights as value. If it is then the
- # weighted sum, using the hash as weight function, will be constrained. The
- # option :substitutions may also be given (with a hash as value), if it is
- # then the sum of the set with all elements replaced according to the hash
- # is constrained. Elements mapped to nil by the weights or substitutions
- # hash are removed from the upper bound of the set. Only one of the two
- # options may be given at the same time.
+ # Produces an IntOperand representing the sum of the values in the
+ # set. One of the following options may also be given:
+ # [:weights] Produces the weighted sum using the specified hash
+ # of weights. The hash should map each value to
+ # that value's weight.
+ # [:substitutions] Produces the sum of the set with all elements
+ # replaced according to the hash.
+ #
+ # Elements not included in the weights or substitutions hash are
+ # removed from the upper bound of the set.
+ #
+ # ==== Examples
+ #
+ # # The sum of +set+.
+ # set.sum
+ #
+ # # The sum of +set+ with primes < 10 given twice the weight.
+ # set.sum(:weights => {2 => 2, 3 => 2, 5 => 2, 7 => 2})
+ #
+ # # The sum of +set+ with odd values in [1,6] being counted as 1.
+ # set.sum(:substitutions => {1 => 1, 3 => 1, 5 => 1})
def sum(options = {:weights => weights = Hash.new(1)})
if options.empty? or options.keys.size > 1
- raise ArgumentError, 'One of the options :weights and :substitutions, ' +
- 'or neither, must be specified.'
+ raise ArgumentError, 'At most one of the options :weights and ' +
+ ':substitutions may be specified.'
end
- params = {:lhs => self}
- unless options.empty?
- case options.keys.first
- when :substitutions: params.update(options)
- when :weights:
- weights = options[:weights]
- substitutions = Hash.new do |hash, key|
- if weights[key].nil?
- hash[key] = nil
- else
- hash[key] = key * weights[key]
- end
+
+ case options.keys.first
+ when :substitutions: subs = options[:substitutions]
+ when :weights:
+ weights = options[:weights]
+ subs = Hash.new do |hash, key|
+ if weights[key].nil?
+ hash[key] = nil
+ else
+ hash[key] = key * weights[key]
end
- params.update(:substitutions => substitutions)
- else raise ArgumentError, "Unrecognized option #{options.keys.first}."
- end
+ end
+ else raise ArgumentError, "Unrecognized option #{options.keys.first}."
end
- Gecode::Constraints::Set::Connection::SumExpressionStub.new(@model, params)
+ Connection::SetSumOperand.new(@model, self, subs)
end
end
-end
-
-module Gecode::Constraints::Set
- class Expression
- # Adds a constraint that forces specified values to be included in the
- # set. This constraint has the side effect of sorting the variables in
- # non-descending order.
- def include(variables)
- unless variables.respond_to? :to_int_var_array
- raise TypeError, "Expected int var enum, got #{variables.class}."
- end
- if @params[:negate]
- raise Gecode::MissingConstraintError, 'A negated include is not ' +
- 'implemented.'
- end
-
- @params.update(:variables => variables)
- @model.add_constraint Connection::IncludeConstraint.new(@model, @params)
- end
- end
-
+
# A module that gathers the classes and modules used in connection
# constraints.
module Connection #:nodoc:
- # Describes a CompositeStub for the min constraint which constrains the
- # minimum value of a set variable.
- #
- # == Examples
- #
- # # Constrains the minimum value of +set+ to be larger than 17.
- # set.min.must > 17
- #
- # # Constrains the minimum value of +set+ to equal the integer variable
- # # +min+.
- # set.min.must == min
- #
- # # Constrains the minimum value of +set+ to not be larger than the
- # # integer variable +ceil+.
- # set.min.must_not > ceil
- #
- # # The same as above but reified with the boolean variable
- # # +is_not_above_ceiling+ and with the strength +domain+ applied.
- # set.min.must_not_be.larger_than(ceil, :reify => :is_not_above_ceiling,
- # :strength => :domain)
- class MinExpressionStub < Gecode::Constraints::Int::CompositeStub
- def constrain_equal(variable, params, constrain)
- set = params[:lhs]
+ class SetMinOperand < Gecode::Int::ShortCircuitEqualityOperand #:nodoc:
+ def initialize(model, set_op)
+ super model
+ @set = set_op
+ end
+
+ def constrain_equal(int_operand, constrain, propagation_options)
+ set = @set.to_set_var
if constrain
- variable.must_be.in set.upper_bound.min..set.lower_bound.min
+ int_operand.must_be.in set.upper_bound.min..set.lower_bound.min
end
- Gecode::Raw::min(@model.active_space, set.bind, variable.bind)
+ Gecode::Raw::min(@model.active_space, set.bind,
+ int_operand.to_int_var.bind)
end
end
- # Describes a CompositeStub for the max constraint which constrains the
- # maximum value of a set variable.
- #
- # == Examples
- #
- # # Constrains the maximum value of +set+ to be larger than 17.
- # set.max.must > 17
- #
- # # Constrains the maximum value of +set+ to equal the integer variable
- # # +max+.
- # set.max.must == max
- #
- # # Constrains the maximum value of +set+ to not be less than the
- # # integer variable +floor+.
- # set.max.must_not < floor
- #
- # # The same as above but reified with the boolean variable
- # # +is_not_below_floor+ and with the strength +domain+ applied.
- # set.max.must_not_be.less_than(ceil, :reify => :is_not_below_floor,
- # :strength => :domain)
- class MaxExpressionStub < Gecode::Constraints::Int::CompositeStub
- def constrain_equal(variable, params, constrain)
- set = params[:lhs]
+ class SetMaxOperand < Gecode::Int::ShortCircuitEqualityOperand #:nodoc:
+ def initialize(model, set_op)
+ super model
+ @set = set_op
+ end
+
+ def constrain_equal(int_operand, constrain, propagation_options)
+ set = @set.to_set_var
if constrain
- variable.must_be.in set.lower_bound.max..set.upper_bound.max
+ int_operand.must_be.in set.upper_bound.min..set.lower_bound.min
end
- Gecode::Raw::max(@model.active_space, set.bind, variable.bind)
+ Gecode::Raw::max(@model.active_space, set.bind,
+ int_operand.to_int_var.bind)
end
end
- # Describes a CompositeStub for the sum constraint which constrains the
- # sum of all values in a set variable.
- #
- # == Examples
- #
- # # Constrains the sum of all values in +set+ to be larger than 17.
- # set.sum.must > 17
- #
- # # Constrains the sum of all values in +set+ to equal the integer
- # # variable +sum+.
- # set.sum.must == sum
- #
- # # Constrains the sum of all values in +set+ to not be larger than the
- # # integer variable +resources+.
- # set.sum.must_not > resources
- #
- # # The same as above but reified with the boolean variable
- # # +not_over_budget+ and with the strength +domain+ applied.
- # set.sum.must_not_be.larger_than(resources, :reify => :not_over_budget,
- # :strength => :domain)
- class SumExpressionStub < Gecode::Constraints::Int::CompositeStub
- def constrain_equal(variable, params, constrain)
- set, subs = params.values_at(:lhs, :substitutions)
+ class SetSumOperand < Gecode::Int::ShortCircuitEqualityOperand #:nodoc:
+ def initialize(model, set_op, subs)
+ super model
+ @set = set_op
+ @subs = subs
+ end
+
+ def constrain_equal(int_operand, constrain, propagation_options)
+ set = @set.to_set_var
lub = set.upper_bound.to_a
- lub.delete_if{ |e| subs[e].nil? }
- substituted_lub = lub.map{ |e| subs[e] }
+ lub.delete_if{ |e| @subs[e].nil? }
+ substituted_lub = lub.map{ |e| @subs[e] }
if constrain
# Compute the theoretical bounds of the weighted sum. This is slightly
# sloppy since we could also use the contents of the greatest lower
# bound.
min = substituted_lub.find_all{ |e| e < 0}.inject(0){ |x, y| x + y }
max = substituted_lub.find_all{ |e| e > 0}.inject(0){ |x, y| x + y }
- variable.must_be.in min..max
+ int_operand.must_be.in min..max
end
Gecode::Raw::weights(@model.active_space, lub, substituted_lub,
- set.bind, variable.bind)
+ set.bind, int_operand.to_int_var.bind)
end
end
-
- # Describes an include constraint, which constrains the set to include the
- # values of the specified enumeration of integer variables.
- #
- # The constraint has the side effect of sorting the integer variables in a
- # non-descending order. It does not support reification nor negation.
- #
- # == Examples
- #
- # # Constrain +set+ to include the values of all variables in
- # # +int_enum+.
- # set.must.include int_enum
- class IncludeConstraint < Gecode::Constraints::Constraint
- def post
- set, variables = @params.values_at(:lhs, :variables)
- Gecode::Raw::match(@model.active_space, set.bind,
- variables.to_int_var_array)
- end
- end
end
-end
\ No newline at end of file
+end