lib/gecoder/interface/constraints/int_enum/distinct.rb in gecoder-0.8.3 vs lib/gecoder/interface/constraints/int_enum/distinct.rb in gecoder-0.9.0

- old
+ new

@@ -1,25 +1,28 @@ -module Gecode - module IntEnumMethods - # Specifies offsets to be used with a distinct constraint. The offsets can - # be specified one by one or as an array of offsets. - def with_offsets(*offsets) - if offsets.kind_of? Enumerable - offsets = *offsets - end - params = {:lhs => self, :offsets => offsets} - - Gecode::Constraints::SimpleExpressionStub.new(@model, params) do |m, ps| - Gecode::Constraints::IntEnum::Expression.new(m, ps) - end - end - end -end - -module Gecode::Constraints::IntEnum - class Expression - # Posts a distinct constraint on the variables in the enum. +module Gecode::IntEnum + class IntEnumConstraintReceiver + # Constrains all integer operands in the enumeration to be distinct + # (different). The constraint can also be used with constant + # offsets, so that the operands, with specified offsets added, must + # be distinct. + # + # The constraint does not support negation nor reification. + # + # ==== Examples + # + # # Constrains all operands in +int_enum+ to be assigned different + # # values. + # int_enum.must_be.distinct + # + # # The same as above, but also selects that the strength +domain+ should + # # be used. + # int_enum.must_be.distinct(:strength => :domain) + # + # # Uses the offset to constrain that no number may be the previous number + # # incremented by one. + # numbers = int_var_array(8, 0..9) + # numbers.must_be.distinct(:offsets => (1..numbers.size).to_a.reverse) def distinct(options = {}) if @params[:negate] # The best we could implement it as from here would be a bunch of # reified pairwise equality constraints. raise Gecode::MissingConstraintError, 'A negated distinct is not ' + @@ -27,48 +30,35 @@ end unless options[:reify].nil? raise ArgumentError, 'Reification is not supported by the distinct ' + 'constraint.' end - + + if options.has_key? :offsets + offsets = options.delete(:offsets) + unless offsets.kind_of? Enumerable + raise TypeError, 'Expected Enumerable as offsets, got ' + + "#{offsets.class}." + end + @params[:offsets] = offsets + end @model.add_constraint Distinct::DistinctConstraint.new(@model, - @params.update(Gecode::Constraints::Util.decode_options(options))) + @params.update(Gecode::Util.decode_options(options))) end end # A module that gathers the classes and modules used in distinct constraints. module Distinct #:nodoc: - # Describes a distinct constraint, which constrains all integer variables - # in an enumeration to be distinct (different). The constraint can also be - # used with constant offsets, so that the variables, with specified offsets - # added, must be distinct. - # - # The constraint does not support negation nor reification. - # - # == Examples - # - # # Constrains all variables in +int_enum+ to be assigned different - # # values. - # int_enum.must_be.distinct - # - # # The same as above, but also selects that the strength +domain+ should - # # be used. - # int_enum.must_be.distinct(:strength => :domain) - # - # # Uses the offset to constrain that no number may be the previous number - # # incremented by one. - # numbers = int_var_array(8, 0..9) - # numbers.with_offset((1..numbers.size).to_a.reverse).must_be.distinct - class DistinctConstraint < Gecode::Constraints::Constraint + class DistinctConstraint < Gecode::Constraint #:nodoc: def post # Bind lhs. - @params[:lhs] = @params[:lhs].to_int_var_array + @params[:lhs] = @params[:lhs].to_int_enum.bind_array # Fetch the parameters to Gecode. params = @params.values_at(:offsets, :lhs) params.delete_if{ |x| x.nil? } params.concat propagation_options Gecode::Raw::distinct(@model.active_space, *params) end end end -end \ No newline at end of file +end