module Gecode class Model # Wraps a custom enumerable so that constraints can be specified using it. # The argument is altered and returned. def wrap_enum(enum) unless enum.kind_of? Enumerable raise TypeError, 'Only enumerables can be wrapped.' end if enum.kind_of? Gecode::EnumMethods raise ArgumentError, 'The enumration is already wrapped.' end elements = enum.to_a if elements.empty? raise ArgumentError, 'Enumerable must not be empty.' end if elements.all?{ |var| var.kind_of? FreeIntVar } class < range.last range end end end # A module containing the methods needed by enumerations containing boolean # variables. Requires that it's included in an enumerable. module BoolEnumMethods include VariableEnumMethods # Returns a bool variable array with all the bound variables. def to_bool_var_array space = @model.active_space unless @bound_space == space elements = to_a @bound_arr = Gecode::Raw::BoolVarArray.new(active_space, elements.size) elements.each_with_index{ |var, index| @bound_arr[index] = var.bind } @bound_space = space end return @bound_arr end alias_method :to_var_array, :to_bool_var_array end # A module containing the methods needed by enumerations containing set # variables. Requires that it's included in an enumerable. module SetEnumMethods include VariableEnumMethods # Returns a set variable array with all the bound variables. def to_set_var_array space = @model.active_space unless @bound_space == space elements = to_a @bound_arr = Gecode::Raw::SetVarArray.new(active_space, elements.size) elements.each_with_index{ |var, index| @bound_arr[index] = var.bind } @bound_space = space end return @bound_arr end alias_method :to_var_array, :to_set_var_array # Returns the range of the union of the contained sets' upper bounds. def upper_bound_range inject(nil) do |range, var| upper_bound = var.upper_bound min = upper_bound.min max = upper_bound.max next min..max if range.nil? range = min..range.last if min < range.first range = range.first..max if max > range.last range end end end # A module containing the methods needed by enumerations containing fixnums. # Requires that it's included in an enumerable. module FixnumEnumMethods include EnumMethods # Returns the smallest range that contains the domains of all integer # variables involved. def domain_range min..max end end end