gecoder-with-gecode 0.8.0 → 0.8.1
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 +11 -1
- data/Rakefile +3 -2
- data/example/raw_bindings.rb +7 -5
- data/example/sudoku-set.rb +0 -3
- data/lib/gecoder/bindings/bindings.rb +35 -1
- data/lib/gecoder/interface/binding_changes.rb +4 -8
- data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +63 -0
- data/lib/gecoder/interface/constraints/bool_enum/{boolean.rb → relation.rb} +8 -6
- data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +26 -2
- data/lib/gecoder/interface/constraints/int_enum/extensional.rb +61 -0
- data/lib/gecoder/interface/constraints/int_enum_constraints.rb +1 -0
- data/lib/gecoder/interface/model.rb +28 -6
- data/lib/gecoder/interface/search.rb +47 -18
- data/lib/gecoder/version.rb +1 -1
- data/specs/constraints/{bool_enum.rb → bool_enum_relation.rb} +5 -5
- data/specs/constraints/constraints.rb +9 -0
- data/specs/constraints/extensional.rb +106 -0
- data/specs/examples.rb +17 -0
- data/specs/search.rb +60 -0
- data/specs/set_var.rb +1 -1
- data/tasks/distribution.rake +38 -22
- data/tasks/rcov.rake +3 -2
- data/tasks/specs.rake +9 -3
- data/tasks/svn.rake +6 -3
- metadata +14 -6
    
        data/CHANGES
    CHANGED
    
    | @@ -1,8 +1,18 @@ | |
| 1 | 
            +
            == Version 0.8.1
         | 
| 2 | 
            +
            This release adds tuple constraints along with a couple of minor features. It 
         | 
| 3 | 
            +
            also fixes a bug introduced in the previous version.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * [#19435] Fixed a bug causing inconsistencies during BAB-search. The bug stopped the send+more=money example from working correctly.
         | 
| 6 | 
            +
            * Fixed the "raw_bindings" and "sudoku-set" examples, which were broken by the 0.8.0 release.
         | 
| 7 | 
            +
            * Integers can now be used to specify singleton lower and upper bounds when creating set variables. 
         | 
| 8 | 
            +
            * Added convenience methods Model#maximize! and Model#minimize! for optimizing single variables.
         | 
| 9 | 
            +
            * Added tuple constraints for enumerations of integer and boolean variables.
         | 
| 10 | 
            +
             | 
| 1 11 | 
             
            == Version 0.8.0
         | 
| 2 12 | 
             
            This release makes the jump from using Gecode 1.3.1 to using Gecode 2.1.1 . 
         | 
| 3 13 | 
             
            The following changes have been made to the interface as a result of the jump.
         | 
| 4 14 |  | 
| 5 | 
            -
            *  | 
| 15 | 
            +
            * Removed the distinct constraint for sets.
         | 
| 6 16 | 
             
            * Added the propagation kind option to the non-set constraints.
         | 
| 7 17 |  | 
| 8 18 | 
             
            == Version 0.7.1
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -4,10 +4,11 @@ require 'rake/rdoctask' | |
| 4 4 | 
             
            require 'rake/gempackagetask'
         | 
| 5 5 |  | 
| 6 6 | 
             
            require 'tasks/all_tasks'
         | 
| 7 | 
            -
            task :default => [:verify_rcov]
         | 
| 7 | 
            +
            task :default => [:verify_rcov, :example_specs]
         | 
| 8 8 |  | 
| 9 9 | 
             
            desc 'Performs the tasks necessary when releasing'
         | 
| 10 | 
            -
            task :release => [: | 
| 10 | 
            +
            task :release => [:clobber, :verify_rcov, :example_specs, :publish_website, 
         | 
| 11 | 
            +
              :publish_packages, :tag]
         | 
| 11 12 |  | 
| 12 13 | 
             
            desc 'Runs all the tests'
         | 
| 13 14 | 
             
            task :test => :specs
         | 
    
        data/example/raw_bindings.rb
    CHANGED
    
    | @@ -12,14 +12,16 @@ s, e, n, d, m, o, r, y = (0..7).to_a.map{ |i| letters.at(i) } | |
| 12 12 | 
             
            Gecode::Raw::post(space, (s * 1000 + e * 100 + n * 10  + d   + 
         | 
| 13 13 | 
             
                                 m * 1000 + o * 100 + r * 10  + e).
         | 
| 14 14 | 
             
                        equal(m * 10000 + o * 1000 + n * 100 + e * 10  + y ), 
         | 
| 15 | 
            -
                        Gecode::Raw::ICL_DEF)
         | 
| 16 | 
            -
            Gecode::Raw::rel(space, s, Gecode::Raw::IRT_NQ, 0, Gecode::Raw::ICL_DEF | 
| 17 | 
            -
            Gecode::Raw:: | 
| 18 | 
            -
            Gecode::Raw:: | 
| 15 | 
            +
                        Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF)
         | 
| 16 | 
            +
            Gecode::Raw::rel(space, s, Gecode::Raw::IRT_NQ, 0, Gecode::Raw::ICL_DEF, 
         | 
| 17 | 
            +
              Gecode::Raw::PK_DEF)
         | 
| 18 | 
            +
            Gecode::Raw::rel(space, m, Gecode::Raw::IRT_NQ, 0, Gecode::Raw::ICL_DEF, 
         | 
| 19 | 
            +
              Gecode::Raw::PK_DEF)
         | 
| 20 | 
            +
            Gecode::Raw::distinct(space, letters, Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF)
         | 
| 19 21 |  | 
| 20 22 | 
             
            # Branching.
         | 
| 21 23 | 
             
            Gecode::Raw::branch(space, letters, 
         | 
| 22 | 
            -
              Gecode::Raw:: | 
| 24 | 
            +
              Gecode::Raw::INT_VAR_SIZE_MIN, Gecode::Raw::INT_VAL_MIN)
         | 
| 23 25 |  | 
| 24 26 | 
             
            # Search
         | 
| 25 27 | 
             
            COPY_DIST = 16
         | 
    
        data/example/sudoku-set.rb
    CHANGED
    
    | @@ -61,9 +61,6 @@ class SudokuSet < Gecode::Model | |
| 61 61 | 
             
                    @sets[i].must_be.disjoint_with @sets[j]
         | 
| 62 62 | 
             
                  end
         | 
| 63 63 | 
             
                end
         | 
| 64 | 
            -
                # The above implies that the sets must be distinct (since cardinality 0 is
         | 
| 65 | 
            -
                # not allowed), but we also explicitly add the distinctness constraint.
         | 
| 66 | 
            -
                @sets.must_be.distinct(:size => n)
         | 
| 67 64 |  | 
| 68 65 | 
             
                # The sets must intersect in exactly one element with each row column and
         | 
| 69 66 | 
             
                # block. I.e. an assignable number must be assigned exactly once in each
         | 
| @@ -149,7 +149,7 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b| | |
| 149 149 | 
             
                  enum.add_value "SRT_CMPL"
         | 
| 150 150 | 
             
                end
         | 
| 151 151 |  | 
| 152 | 
            -
                ns.add_enum "SetOpType | 
| 152 | 
            +
                ns.add_enum "SetOpType" do |enum|
         | 
| 153 153 | 
             
                  enum.add_value "SOT_UNION"
         | 
| 154 154 | 
             
                  enum.add_value "SOT_DUNION"
         | 
| 155 155 | 
             
                  enum.add_value "SOT_INTER"
         | 
| @@ -337,6 +337,20 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b| | |
| 337 337 | 
             
                  klass.add_method "debug"
         | 
| 338 338 | 
             
                end
         | 
| 339 339 |  | 
| 340 | 
            +
                ns.add_cxx_class "TupleSet" do |klass|
         | 
| 341 | 
            +
                  klass.add_constructor
         | 
| 342 | 
            +
                  
         | 
| 343 | 
            +
                  klass.add_method "add" do |method|
         | 
| 344 | 
            +
                    method.add_parameter "Gecode::IntArgs", "tuple"
         | 
| 345 | 
            +
                  end
         | 
| 346 | 
            +
                  
         | 
| 347 | 
            +
                  klass.add_method "finalize"
         | 
| 348 | 
            +
                  
         | 
| 349 | 
            +
                  klass.add_method "finalized", "bool"
         | 
| 350 | 
            +
                  
         | 
| 351 | 
            +
                  klass.add_method "tuples", "int"
         | 
| 352 | 
            +
                end
         | 
| 353 | 
            +
                
         | 
| 340 354 | 
             
                ns.add_cxx_class "MBranchingDesc" do |klass|
         | 
| 341 355 | 
             
                  klass.bindname = "BranchingDesc"
         | 
| 342 356 | 
             
                  klass.add_constructor
         | 
| @@ -1207,6 +1221,26 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b| | |
| 1207 1221 | 
             
                  func.add_parameter "Gecode::PropKind", "pk"
         | 
| 1208 1222 | 
             
                end
         | 
| 1209 1223 |  | 
| 1224 | 
            +
                ns.add_function "extensional", "void" do |func|
         | 
| 1225 | 
            +
                  func.add_parameter "Gecode::MSpace*", "home"
         | 
| 1226 | 
            +
                  func.add_parameter "Gecode::MIntVarArray *", "x" do |param|
         | 
| 1227 | 
            +
                    param.custom_conversion = "*ruby2Gecode_MIntVarArrayPtr(argv[1], 2)->ptr()"
         | 
| 1228 | 
            +
                  end
         | 
| 1229 | 
            +
                  func.add_parameter "Gecode::TupleSet", "t"
         | 
| 1230 | 
            +
                  func.add_parameter "Gecode::IntConLevel", "icl"
         | 
| 1231 | 
            +
                  func.add_parameter "Gecode::PropKind", "pk"
         | 
| 1232 | 
            +
                end
         | 
| 1233 | 
            +
                
         | 
| 1234 | 
            +
                ns.add_function "extensional", "void" do |func|
         | 
| 1235 | 
            +
                  func.add_parameter "Gecode::MSpace*", "home"
         | 
| 1236 | 
            +
                  func.add_parameter "Gecode::MBoolVarArray *", "x" do |param|
         | 
| 1237 | 
            +
                    param.custom_conversion = "*ruby2Gecode_MBoolVarArrayPtr(argv[1], 2)->ptr()"
         | 
| 1238 | 
            +
                  end
         | 
| 1239 | 
            +
                  func.add_parameter "Gecode::TupleSet", "t"
         | 
| 1240 | 
            +
                  func.add_parameter "Gecode::IntConLevel", "icl"
         | 
| 1241 | 
            +
                  func.add_parameter "Gecode::PropKind", "pk"
         | 
| 1242 | 
            +
                end
         | 
| 1243 | 
            +
              
         | 
| 1210 1244 | 
             
            # 		ns.add_function "regular", "void" do |func|
         | 
| 1211 1245 | 
             
            # 			func.add_parameter "Gecode::MSpace*", "home"
         | 
| 1212 1246 | 
             
            # 			func.add_parameter "Gecode::MIntVarArray *", "x" do |param|
         | 
| @@ -291,15 +291,11 @@ module Gecode | |
| 291 291 |  | 
| 292 292 | 
             
                  private
         | 
| 293 293 |  | 
| 294 | 
            -
                  # Transforms a lub or glb domain given as a range or enumeration  | 
| 295 | 
            -
                  # or more parameters that describe the domain to  | 
| 294 | 
            +
                  # Transforms a lub or glb domain given as a fixnum, range or enumeration 
         | 
| 295 | 
            +
                  # into one or more parameters that describe the domain to 
         | 
| 296 | 
            +
                  # Gecode::Raw::SetVar .
         | 
| 296 297 | 
             
                  def domain_to_args(domain)
         | 
| 297 | 
            -
                     | 
| 298 | 
            -
                      return domain.first, domain.last
         | 
| 299 | 
            -
                    else
         | 
| 300 | 
            -
                      elements = domain.to_a
         | 
| 301 | 
            -
                      return Gecode::Raw::IntSet.new(domain, domain.size)
         | 
| 302 | 
            -
                    end
         | 
| 298 | 
            +
                    Gecode::Constraints::Util.constant_set_to_int_set(domain)
         | 
| 303 299 | 
             
                  end
         | 
| 304 300 |  | 
| 305 301 | 
             
                  # Creates a new storage array for bool variables.
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            module Gecode::Constraints::BoolEnum
         | 
| 2 | 
            +
              class Expression
         | 
| 3 | 
            +
                # Posts an equality constraint on the variables in the enum.
         | 
| 4 | 
            +
                def in(tuples, options = {})
         | 
| 5 | 
            +
                  if @params[:negate]
         | 
| 6 | 
            +
                    raise Gecode::MissingConstraintError, 'A negated tuple constraint is ' +
         | 
| 7 | 
            +
                      'not implemented.'
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                  unless options[:reify].nil?
         | 
| 10 | 
            +
                    raise ArgumentError, 'Reification is not supported by the tuple ' + 
         | 
| 11 | 
            +
                      'constraint.'
         | 
| 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.'
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                
         | 
| 23 | 
            +
                  @params[:tuples] = tuples
         | 
| 24 | 
            +
                  @model.add_constraint Extensional::TupleConstraint.new(@model, 
         | 
| 25 | 
            +
                    @params.update(Gecode::Constraints::Util.decode_options(options)))
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
              
         | 
| 29 | 
            +
              # A module that gathers the classes and modules used in extensional 
         | 
| 30 | 
            +
              # constraints.
         | 
| 31 | 
            +
              module Extensional #:nodoc:
         | 
| 32 | 
            +
                # Describes a tuple constraint, which constrains the variables in an 
         | 
| 33 | 
            +
                # boolean enumeration to be equal to one of the specified tuples. Neither 
         | 
| 34 | 
            +
                # negation nor reification is supported.
         | 
| 35 | 
            +
                # 
         | 
| 36 | 
            +
                # == Example
         | 
| 37 | 
            +
                # 
         | 
| 38 | 
            +
                #   # Constrains the three boolean variables in +bools+ to either
         | 
| 39 | 
            +
                #   # be true, false, true, or false, false, true.
         | 
| 40 | 
            +
                #   bools.must_be.in [[true, false, true], [false, false, true]]
         | 
| 41 | 
            +
                #
         | 
| 42 | 
            +
                #   # The same as above, but preferring speed over low memory usage.
         | 
| 43 | 
            +
                #   bools.must_be.in([[true, false, true], [false, false, true]], 
         | 
| 44 | 
            +
                #     :kind => :speed)
         | 
| 45 | 
            +
                class TupleConstraint < Gecode::Constraints::Constraint
         | 
| 46 | 
            +
                  def post
         | 
| 47 | 
            +
                    # Bind lhs.
         | 
| 48 | 
            +
                    lhs = @params[:lhs].to_bool_var_array
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    # Create the tuple set.
         | 
| 51 | 
            +
                    tuple_set = Gecode::Raw::TupleSet.new
         | 
| 52 | 
            +
                    @params[:tuples].each do |tuple|
         | 
| 53 | 
            +
                      tuple_set.add tuple.map{ |b| b ? 1 : 0 }
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                    tuple_set.finalize
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    # Post the constraint.
         | 
| 58 | 
            +
                    Gecode::Raw::extensional(@model.active_space, lhs, tuple_set, 
         | 
| 59 | 
            +
                      *propagation_options)
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            end
         | 
| @@ -3,21 +3,23 @@ module Gecode | |
| 3 3 | 
             
                # Produces an expression that can be handled as if it was a variable 
         | 
| 4 4 | 
             
                # representing the conjunction of all boolean variables in the enumeration.
         | 
| 5 5 | 
             
                def conjunction
         | 
| 6 | 
            -
                  return Gecode::Constraints::BoolEnum::ConjunctionStub.new(
         | 
| 6 | 
            +
                  return Gecode::Constraints::BoolEnum::Relation::ConjunctionStub.new(
         | 
| 7 7 | 
             
                    @model, :lhs => self)
         | 
| 8 8 | 
             
                end
         | 
| 9 9 |  | 
| 10 10 | 
             
                # Produces an expression that can be handled as if it was a variable 
         | 
| 11 11 | 
             
                # representing the disjunction of all boolean variables in the enumeration.
         | 
| 12 12 | 
             
                def disjunction
         | 
| 13 | 
            -
                  return Gecode::Constraints::BoolEnum::DisjunctionStub.new(
         | 
| 13 | 
            +
                  return Gecode::Constraints::BoolEnum::Relation::DisjunctionStub.new(
         | 
| 14 14 | 
             
                    @model, :lhs => self)
         | 
| 15 15 | 
             
                end
         | 
| 16 16 | 
             
              end
         | 
| 17 | 
            -
             | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            module Gecode::Constraints::BoolEnum
         | 
| 18 20 | 
             
              # A module that gathers the classes and modules used by boolean enumeration 
         | 
| 19 | 
            -
              # constraints.
         | 
| 20 | 
            -
              module  | 
| 21 | 
            +
              # relation constraints.
         | 
| 22 | 
            +
              module Relation #:nodoc:
         | 
| 21 23 | 
             
                # Describes a CompositeStub for the conjunction constraint, which constrain
         | 
| 22 24 | 
             
                # the conjunction of all boolean variables in an enumeration.
         | 
| 23 25 | 
             
                # 
         | 
| @@ -83,4 +85,4 @@ module Gecode | |
| 83 85 | 
             
                  end
         | 
| 84 86 | 
             
                end
         | 
| 85 87 | 
             
              end
         | 
| 86 | 
            -
            end
         | 
| 88 | 
            +
            end
         | 
| @@ -1,8 +1,32 @@ | |
| 1 | 
            -
            module Gecode | 
| 1 | 
            +
            module Gecode
         | 
| 2 | 
            +
              module BoolEnumMethods
         | 
| 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::BoolEnum::Expression.new(@model, params)
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
              
         | 
| 2 14 | 
             
              # A module containing constraints that have enumerations of boolean variables 
         | 
| 3 15 | 
             
              # as left hand side.
         | 
| 4 16 | 
             
              module Constraints::BoolEnum
         | 
| 17 | 
            +
                # Expressions with bool enums as left hand sides.
         | 
| 18 | 
            +
                class Expression < Gecode::Constraints::Expression #:nodoc:
         | 
| 19 | 
            +
                  # Raises TypeError unless the left hand side is a bool enum.
         | 
| 20 | 
            +
                  def initialize(model, params)
         | 
| 21 | 
            +
                    super
         | 
| 22 | 
            +
                    
         | 
| 23 | 
            +
                    unless params[:lhs].respond_to? :to_bool_var_array
         | 
| 24 | 
            +
                      raise TypeError, 'Must have bool enum as left hand side.'
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 5 28 | 
             
              end
         | 
| 6 29 | 
             
            end
         | 
| 7 30 |  | 
| 8 | 
            -
            require 'gecoder/interface/constraints/bool_enum/ | 
| 31 | 
            +
            require 'gecoder/interface/constraints/bool_enum/relation'
         | 
| 32 | 
            +
            require 'gecoder/interface/constraints/bool_enum/extensional'
         | 
| @@ -0,0 +1,61 @@ | |
| 1 | 
            +
            module Gecode::Constraints::IntEnum
         | 
| 2 | 
            +
              class Expression
         | 
| 3 | 
            +
                # Posts an equality constraint on the variables in the enum.
         | 
| 4 | 
            +
                def in(tuples, options = {})
         | 
| 5 | 
            +
                  if @params[:negate]
         | 
| 6 | 
            +
                    raise Gecode::MissingConstraintError, 'A negated tuple constraint is ' +
         | 
| 7 | 
            +
                      'not implemented.'
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                  unless options[:reify].nil?
         | 
| 10 | 
            +
                    raise ArgumentError, 'Reification is not supported by the tuple ' + 
         | 
| 11 | 
            +
                      'constraint.'
         | 
| 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| tuple.all?{ |x| x.kind_of? Fixnum }}
         | 
| 19 | 
            +
                    raise TypeError, 'All tuples must contain Fixnum.'
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                
         | 
| 22 | 
            +
                  @params[:tuples] = tuples
         | 
| 23 | 
            +
                  @model.add_constraint Extensional::TupleConstraint.new(@model, 
         | 
| 24 | 
            +
                    @params.update(Gecode::Constraints::Util.decode_options(options)))
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
              
         | 
| 28 | 
            +
              # A module that gathers the classes and modules used in extensional 
         | 
| 29 | 
            +
              # constraints.
         | 
| 30 | 
            +
              module Extensional #:nodoc:
         | 
| 31 | 
            +
                # Describes a tuple constraint, which constrains all the variables in an 
         | 
| 32 | 
            +
                # enumeration of integer variables to be equal to one of the specified 
         | 
| 33 | 
            +
                # tuples. Neither negation nor reification is supported.
         | 
| 34 | 
            +
                # 
         | 
| 35 | 
            +
                # == Example
         | 
| 36 | 
            +
                # 
         | 
| 37 | 
            +
                #   # Constrains the two integer variables in +numbers+ to either have 
         | 
| 38 | 
            +
                #   # values 1 and 7, or values 47 and 11.
         | 
| 39 | 
            +
                #   numbers.must_be.in [[1,7], [47,11]]
         | 
| 40 | 
            +
                #
         | 
| 41 | 
            +
                #   # The same as above, but preferring speed over low memory usage.
         | 
| 42 | 
            +
                #   numbers.must_be.in([[1,7], [47,11]], :kind => :speed)
         | 
| 43 | 
            +
                class TupleConstraint < Gecode::Constraints::Constraint
         | 
| 44 | 
            +
                  def post
         | 
| 45 | 
            +
                    # Bind lhs.
         | 
| 46 | 
            +
                    lhs = @params[:lhs].to_int_var_array
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    # Create the tuple set.
         | 
| 49 | 
            +
                    tuple_set = Gecode::Raw::TupleSet.new
         | 
| 50 | 
            +
                    @params[:tuples].each do |tuple|
         | 
| 51 | 
            +
                      tuple_set.add tuple
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                    tuple_set.finalize
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    # Post the constraint.
         | 
| 56 | 
            +
                    Gecode::Raw::extensional(@model.active_space, lhs, tuple_set, 
         | 
| 57 | 
            +
                      *propagation_options)
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
            end
         | 
| @@ -35,3 +35,4 @@ require 'gecoder/interface/constraints/int_enum/element' | |
| 35 35 | 
             
            require 'gecoder/interface/constraints/int_enum/count'
         | 
| 36 36 | 
             
            require 'gecoder/interface/constraints/int_enum/sort'
         | 
| 37 37 | 
             
            require 'gecoder/interface/constraints/int_enum/arithmetic'
         | 
| 38 | 
            +
            require 'gecoder/interface/constraints/int_enum/extensional'
         | 
| @@ -67,11 +67,11 @@ module Gecode | |
| 67 67 | 
             
                end
         | 
| 68 68 |  | 
| 69 69 | 
             
                # Creates a set variable with the specified domain for greatest lower bound
         | 
| 70 | 
            -
                # and least upper bound (specified as either a range or enum). If  | 
| 71 | 
            -
                # are specified then the empty set is used as greates lower bound  | 
| 72 | 
            -
                # universe as least upper bound. A range for the allowed cardinality | 
| 73 | 
            -
                # set can also be specified, if none is specified, or nil is given,  | 
| 74 | 
            -
                # default range (anything) will be used. If only a single Fixnum is 
         | 
| 70 | 
            +
                # and least upper bound (specified as either a fixnum, range or enum). If 
         | 
| 71 | 
            +
                # no bounds are specified then the empty set is used as greates lower bound 
         | 
| 72 | 
            +
                # and the universe as least upper bound. A range for the allowed cardinality
         | 
| 73 | 
            +
                # of the set can also be specified, if none is specified, or nil is given, 
         | 
| 74 | 
            +
                # then the default range (anything) will be used. If only a single Fixnum is 
         | 
| 75 75 | 
             
                # specified as cardinality_range then it's used as lower bound.
         | 
| 76 76 | 
             
                def set_var(glb_domain = [], lub_domain = 
         | 
| 77 77 | 
             
                    Gecode::Raw::SetLimits::MIN..Gecode::Raw::SetLimits::MAX, 
         | 
| @@ -220,6 +220,8 @@ module Gecode | |
| 220 220 | 
             
                  if glb.kind_of?(Range) and lub.kind_of?(Range)
         | 
| 221 221 | 
             
                    glb.first >= lub.first and glb.last <= lub.last
         | 
| 222 222 | 
             
                  else
         | 
| 223 | 
            +
                    glb = [glb] if glb.kind_of?(Fixnum)
         | 
| 224 | 
            +
                    lub = [lub] if lub.kind_of?(Fixnum)
         | 
| 223 225 | 
             
                    (glb.to_a - lub.to_a).empty?
         | 
| 224 226 | 
             
                  end
         | 
| 225 227 | 
             
                end
         | 
| @@ -232,7 +234,8 @@ module Gecode | |
| 232 234 | 
             
                # Retrieves the currently selected space, the one which constraints and 
         | 
| 233 235 | 
             
                # variables should be bound to.
         | 
| 234 236 | 
             
                def selected_space
         | 
| 235 | 
            -
                  @active_space  | 
| 237 | 
            +
                  return @active_space unless @active_space.nil?
         | 
| 238 | 
            +
                  self.active_space = base_space
         | 
| 236 239 | 
             
                end
         | 
| 237 240 |  | 
| 238 241 | 
             
                # Retrieves the space that should be used for variable creation.
         | 
| @@ -243,9 +246,28 @@ module Gecode | |
| 243 246 | 
             
                # Refreshes all cached variables. This should be called if the variables
         | 
| 244 247 | 
             
                # in an existing space were changed.
         | 
| 245 248 | 
             
                def refresh_variables
         | 
| 249 | 
            +
                  return if @variables.nil?
         | 
| 246 250 | 
             
                  @variables.each do |variable|
         | 
| 247 251 | 
             
                    variable.refresh if variable.cached?
         | 
| 248 252 | 
             
                  end
         | 
| 249 253 | 
             
                end
         | 
| 254 | 
            +
                
         | 
| 255 | 
            +
                # Executes any interactions with Gecode still waiting in the queue 
         | 
| 256 | 
            +
                # (emptying the queue) in the process.
         | 
| 257 | 
            +
                def perform_queued_gecode_interactions
         | 
| 258 | 
            +
                  allow_space_access do
         | 
| 259 | 
            +
                    gecode_interaction_queue.each{ |con| con.call }
         | 
| 260 | 
            +
                    gecode_interaction_queue.clear # Empty the queue.
         | 
| 261 | 
            +
                  end
         | 
| 262 | 
            +
                end
         | 
| 263 | 
            +
                
         | 
| 264 | 
            +
                # Switches the active space used (the space from which variables are read
         | 
| 265 | 
            +
                # and to which constraints are posted). @active_space should never be 
         | 
| 266 | 
            +
                # assigned directly.
         | 
| 267 | 
            +
                def active_space=(new_space)
         | 
| 268 | 
            +
                  @active_space = new_space
         | 
| 269 | 
            +
                  new_space.refresh
         | 
| 270 | 
            +
                  refresh_variables
         | 
| 271 | 
            +
                end    
         | 
| 250 272 | 
             
              end
         | 
| 251 273 | 
             
            end
         | 
| @@ -6,14 +6,14 @@ module Gecode | |
| 6 6 | 
             
                def solve!
         | 
| 7 7 | 
             
                  space = dfs_engine.next
         | 
| 8 8 | 
             
                  return nil if space.nil?
         | 
| 9 | 
            -
                   | 
| 9 | 
            +
                  self.active_space = space
         | 
| 10 10 | 
             
                  return self
         | 
| 11 11 | 
             
                end
         | 
| 12 12 |  | 
| 13 13 | 
             
                # Returns to the original state, before any search was made (but propagation 
         | 
| 14 14 | 
             
                # might have been performed). Returns the reset model.
         | 
| 15 15 | 
             
                def reset!
         | 
| 16 | 
            -
                   | 
| 16 | 
            +
                  self.active_space = base_space
         | 
| 17 17 | 
             
                  return self
         | 
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| @@ -30,7 +30,9 @@ module Gecode | |
| 30 30 | 
             
                # Yields each solution that the model has.
         | 
| 31 31 | 
             
                def each_solution(&block)
         | 
| 32 32 | 
             
                  dfs = dfs_engine
         | 
| 33 | 
            -
                   | 
| 33 | 
            +
                  next_solution = nil
         | 
| 34 | 
            +
                  while not (next_solution = dfs.next).nil?
         | 
| 35 | 
            +
                    self.active_space = next_solution
         | 
| 34 36 | 
             
                    yield self
         | 
| 35 37 | 
             
                  end
         | 
| 36 38 | 
             
                  self.reset!
         | 
| @@ -54,10 +56,10 @@ module Gecode | |
| 54 56 |  | 
| 55 57 | 
             
                  # Set the method used for constrain calls by the BAB-search.
         | 
| 56 58 | 
             
                  Model.constrain_proc = lambda do |home_space, best_space|
         | 
| 57 | 
            -
                     | 
| 59 | 
            +
                    self.active_space = best_space
         | 
| 58 60 | 
             
                    @variable_creation_space = home_space
         | 
| 59 61 | 
             
                    yield(self, self)
         | 
| 60 | 
            -
                     | 
| 62 | 
            +
                    self.active_space = home_space
         | 
| 61 63 | 
             
                    @variable_creation_space = nil
         | 
| 62 64 |  | 
| 63 65 | 
             
                    perform_queued_gecode_interactions
         | 
| @@ -74,13 +76,49 @@ module Gecode | |
| 74 76 | 
             
                  Model.constrain_proc = nil
         | 
| 75 77 | 
             
                  return nil if result.nil?
         | 
| 76 78 |  | 
| 77 | 
            -
                  #  | 
| 78 | 
            -
                  result | 
| 79 | 
            -
                  refresh_variables
         | 
| 80 | 
            -
                  @active_space = result
         | 
| 79 | 
            +
                  # Switch to the result.
         | 
| 80 | 
            +
                  self.active_space = result
         | 
| 81 81 | 
             
                  return self
         | 
| 82 82 | 
             
                end
         | 
| 83 83 |  | 
| 84 | 
            +
                # Finds the solution that maximizes a given integer variable. The name of 
         | 
| 85 | 
            +
                # the method that accesses the variable from the model should be given. To 
         | 
| 86 | 
            +
                # for instance maximize a variable named "profit", that's accessible through 
         | 
| 87 | 
            +
                # the model, one would use the following.
         | 
| 88 | 
            +
                #
         | 
| 89 | 
            +
                #   model.maximize! :profit
         | 
| 90 | 
            +
                #
         | 
| 91 | 
            +
                # Returns nil if there is no solution.
         | 
| 92 | 
            +
                def maximize!(var)
         | 
| 93 | 
            +
                  variable = self.method(var).call
         | 
| 94 | 
            +
                  unless variable.kind_of? Gecode::FreeIntVar
         | 
| 95 | 
            +
                    raise ArgumentError.new("Expected integer variable, got #{variable.class}.")
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
                  
         | 
| 98 | 
            +
                  optimize! do |model, best_so_far|
         | 
| 99 | 
            +
                    model.method(var).call.must > best_so_far.method(var).call.value
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
                
         | 
| 103 | 
            +
                # Finds the solution that minimizes a given integer variable. The name of 
         | 
| 104 | 
            +
                # the method that accesses the variable from the model should be given. To 
         | 
| 105 | 
            +
                # for instance minimize a variable named "cost", that's accessible through 
         | 
| 106 | 
            +
                # the model, one would use the following.
         | 
| 107 | 
            +
                #
         | 
| 108 | 
            +
                #   model.minimize! :cost
         | 
| 109 | 
            +
                #
         | 
| 110 | 
            +
                # Returns nil if there is no solution.
         | 
| 111 | 
            +
                def minimize!(var)
         | 
| 112 | 
            +
                  variable = self.method(var).call
         | 
| 113 | 
            +
                  unless variable.kind_of? Gecode::FreeIntVar
         | 
| 114 | 
            +
                    raise ArgumentError.new("Expected integer variable, got #{variable.class}.")
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
                  
         | 
| 117 | 
            +
                  optimize! do |model, best_so_far|
         | 
| 118 | 
            +
                    model.method(var).call.must < best_so_far.method(var).call.value
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
                
         | 
| 84 122 | 
             
                class <<self 
         | 
| 85 123 | 
             
                  # Sets the proc that should be used to handle constrain requests.
         | 
| 86 124 | 
             
                  def constrain_proc=(proc) #:nodoc:
         | 
| @@ -111,14 +149,5 @@ module Gecode | |
| 111 149 | 
             
                    Gecode::Raw::Search::Config::ADAPTIVE_DISTANCE, 
         | 
| 112 150 | 
             
                    nil)
         | 
| 113 151 | 
             
                end
         | 
| 114 | 
            -
                
         | 
| 115 | 
            -
                # Executes any interactions with Gecode still waiting in the queue 
         | 
| 116 | 
            -
                # (emptying the queue) in the process.
         | 
| 117 | 
            -
                def perform_queued_gecode_interactions
         | 
| 118 | 
            -
                  allow_space_access do
         | 
| 119 | 
            -
                    gecode_interaction_queue.each{ |con| con.call }
         | 
| 120 | 
            -
                    gecode_interaction_queue.clear # Empty the queue.
         | 
| 121 | 
            -
                  end
         | 
| 122 | 
            -
                end
         | 
| 123 152 | 
             
              end
         | 
| 124 153 | 
             
            end
         | 
    
        data/lib/gecoder/version.rb
    CHANGED
    
    
| @@ -17,7 +17,7 @@ end | |
| 17 17 |  | 
| 18 18 | 
             
            # Expects @stub, which contains the started constraint and @compute_result which 
         | 
| 19 19 | 
             
            # computes whether the left hand side is true or not.
         | 
| 20 | 
            -
            describe 'bool enum constraint', :shared => true do
         | 
| 20 | 
            +
            describe 'bool enum relation constraint', :shared => true do
         | 
| 21 21 | 
             
              it 'should handle being constrained to be true' do
         | 
| 22 22 | 
             
                @stub.must_be.true
         | 
| 23 23 | 
             
                @model.solve!
         | 
| @@ -67,7 +67,7 @@ describe 'bool enum constraint', :shared => true do | |
| 67 67 | 
             
              end
         | 
| 68 68 | 
             
            end
         | 
| 69 69 |  | 
| 70 | 
            -
            describe Gecode::Constraints::BoolEnum, ' (conjunction)' do
         | 
| 70 | 
            +
            describe Gecode::Constraints::BoolEnum::Relation, ' (conjunction)' do
         | 
| 71 71 | 
             
              before do
         | 
| 72 72 | 
             
                @model = BoolEnumSampleProblem.new
         | 
| 73 73 | 
             
                @bools = @model.bools
         | 
| @@ -109,11 +109,11 @@ describe Gecode::Constraints::BoolEnum, ' (conjunction)' do | |
| 109 109 | 
             
                @compute_result = lambda{ @bools.all?{ |b| b.value } }
         | 
| 110 110 | 
             
              end
         | 
| 111 111 |  | 
| 112 | 
            -
              it_should_behave_like 'bool enum constraint'
         | 
| 112 | 
            +
              it_should_behave_like 'bool enum relation constraint'
         | 
| 113 113 | 
             
              it_should_behave_like 'reifiable constraint'
         | 
| 114 114 | 
             
            end
         | 
| 115 115 |  | 
| 116 | 
            -
            describe Gecode::Constraints::BoolEnum, ' (disjunction)' do
         | 
| 116 | 
            +
            describe Gecode::Constraints::BoolEnum::Relation, ' (disjunction)' do
         | 
| 117 117 | 
             
              before do
         | 
| 118 118 | 
             
                @model = BoolEnumSampleProblem.new
         | 
| 119 119 | 
             
                @bools = @model.bools
         | 
| @@ -155,6 +155,6 @@ describe Gecode::Constraints::BoolEnum, ' (disjunction)' do | |
| 155 155 | 
             
                @compute_result = lambda{ @bools.any?{ |b| b.value } }
         | 
| 156 156 | 
             
              end
         | 
| 157 157 |  | 
| 158 | 
            -
              it_should_behave_like 'bool enum constraint'
         | 
| 158 | 
            +
              it_should_behave_like 'bool enum relation constraint'
         | 
| 159 159 | 
             
              it_should_behave_like 'reifiable constraint'
         | 
| 160 160 | 
             
            end
         | 
| @@ -17,6 +17,15 @@ describe Gecode::Constraints::IntEnum::Expression do | |
| 17 17 | 
             
              end
         | 
| 18 18 | 
             
            end
         | 
| 19 19 |  | 
| 20 | 
            +
            describe Gecode::Constraints::BoolEnum::Expression do
         | 
| 21 | 
            +
              it 'should raise error unless lhs is a bool enum' do
         | 
| 22 | 
            +
                lambda do
         | 
| 23 | 
            +
                  Gecode::Constraints::BoolEnum::Expression.new(Gecode::Model.new, 
         | 
| 24 | 
            +
                    :lhs => 'foo', :negate => false)
         | 
| 25 | 
            +
                end.should raise_error(TypeError)
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| 28 | 
            +
             | 
| 20 29 | 
             
            describe Gecode::Constraints::SetEnum::Expression do
         | 
| 21 30 | 
             
              it 'should raise error unless lhs is a set enum' do
         | 
| 22 31 | 
             
                lambda do
         | 
| @@ -0,0 +1,106 @@ | |
| 1 | 
            +
            require File.dirname(__FILE__) + '/../spec_helper'
         | 
| 2 | 
            +
            require File.dirname(__FILE__) + '/constraint_helper'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe Gecode::Constraints::IntEnum::Extensional do
         | 
| 5 | 
            +
              before do
         | 
| 6 | 
            +
                @model = Gecode::Model.new
         | 
| 7 | 
            +
                @tuples = [[1,7], [5,1]]
         | 
| 8 | 
            +
                @digits = @model.int_var_array(2, 0..9)
         | 
| 9 | 
            +
                @model.branch_on @digits
         | 
| 10 | 
            +
                
         | 
| 11 | 
            +
                @invoke_options = lambda do |hash| 
         | 
| 12 | 
            +
                  @digits.must_be.in(@tuples, hash) 
         | 
| 13 | 
            +
                  @model.solve!
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
                @expect_options = option_expectation do |strength, kind, reif_var|
         | 
| 16 | 
            +
                  Gecode::Raw.should_receive(:extensional).once.with(
         | 
| 17 | 
            +
                    an_instance_of(Gecode::Raw::Space), 
         | 
| 18 | 
            +
                    an_instance_of(Gecode::Raw::IntVarArray), 
         | 
| 19 | 
            +
                    an_instance_of(Gecode::Raw::TupleSet), strength, kind)
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
              
         | 
| 23 | 
            +
              it 'should constrain the domain of all variables' do
         | 
| 24 | 
            +
                @digits.must_be.in @tuples
         | 
| 25 | 
            +
                
         | 
| 26 | 
            +
                found_solutions = []
         | 
| 27 | 
            +
                @model.each_solution do |m|
         | 
| 28 | 
            +
                  found_solutions << @digits.values
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
                
         | 
| 31 | 
            +
                found_solutions.size.should == 2
         | 
| 32 | 
            +
                (found_solutions - @tuples).should be_empty
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
              
         | 
| 35 | 
            +
              it 'should not allow negation' do
         | 
| 36 | 
            +
                lambda do 
         | 
| 37 | 
            +
                  @digits.must_not_be.in @tuples
         | 
| 38 | 
            +
                end.should raise_error(Gecode::MissingConstraintError) 
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
              
         | 
| 41 | 
            +
              it 'should raise error if the right hand side is not an enumeration' do
         | 
| 42 | 
            +
                lambda{ @digits.must_be.in 4711 }.should raise_error(TypeError)
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
              
         | 
| 45 | 
            +
              it 'should raise error if the right hand side does not contain tuples' do
         | 
| 46 | 
            +
                lambda{ @digits.must_be.in [17, 4711] }.should raise_error(TypeError)
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
              
         | 
| 49 | 
            +
              it 'should raise error if the right hand side does not contain integer tuples' do
         | 
| 50 | 
            +
                lambda{ @digits.must_be.in ['hello'] }.should raise_error(TypeError)
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
              
         | 
| 53 | 
            +
              it_should_behave_like 'non-reifiable constraint'
         | 
| 54 | 
            +
            end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            describe Gecode::Constraints::BoolEnum::Extensional do
         | 
| 57 | 
            +
              before do
         | 
| 58 | 
            +
                @model = Gecode::Model.new
         | 
| 59 | 
            +
                @tuples = [[true, false, true], [false, false, true]]
         | 
| 60 | 
            +
                @bools = @model.bool_var_array(3)
         | 
| 61 | 
            +
                @model.branch_on @bools
         | 
| 62 | 
            +
                
         | 
| 63 | 
            +
                @invoke_options = lambda do |hash| 
         | 
| 64 | 
            +
                  @bools.must_be.in(@tuples, hash) 
         | 
| 65 | 
            +
                  @model.solve!
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
                @expect_options = option_expectation do |strength, kind, reif_var|
         | 
| 68 | 
            +
                  Gecode::Raw.should_receive(:extensional).once.with(
         | 
| 69 | 
            +
                    an_instance_of(Gecode::Raw::Space), 
         | 
| 70 | 
            +
                    an_instance_of(Gecode::Raw::BoolVarArray), 
         | 
| 71 | 
            +
                    an_instance_of(Gecode::Raw::TupleSet), strength, kind)
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
              
         | 
| 75 | 
            +
              it 'should constrain the domain of all variables' do
         | 
| 76 | 
            +
                @bools.must_be.in @tuples
         | 
| 77 | 
            +
                
         | 
| 78 | 
            +
                found_solutions = []
         | 
| 79 | 
            +
                @model.each_solution do |m|
         | 
| 80 | 
            +
                  found_solutions << @bools.values
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
                
         | 
| 83 | 
            +
                found_solutions.size.should == 2
         | 
| 84 | 
            +
                (found_solutions - @tuples).should be_empty
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
              
         | 
| 87 | 
            +
              it 'should not allow negation' do
         | 
| 88 | 
            +
                lambda do 
         | 
| 89 | 
            +
                  @bools.must_not_be.in @tuples
         | 
| 90 | 
            +
                end.should raise_error(Gecode::MissingConstraintError) 
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
              
         | 
| 93 | 
            +
              it 'should raise error if the right hand side is not an enumeration' do
         | 
| 94 | 
            +
                lambda{ @bools.must_be.in true }.should raise_error(TypeError)
         | 
| 95 | 
            +
              end
         | 
| 96 | 
            +
              
         | 
| 97 | 
            +
              it 'should raise error if the right hand side does not contain tuples' do
         | 
| 98 | 
            +
                lambda{ @bools.must_be.in [true, false] }.should raise_error(TypeError)
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
              
         | 
| 101 | 
            +
              it 'should raise error if the right hand side does not contain boolean tuples' do
         | 
| 102 | 
            +
                lambda{ @bools.must_be.in ['hello'] }.should raise_error(TypeError)
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
              
         | 
| 105 | 
            +
              it_should_behave_like 'non-reifiable constraint'
         | 
| 106 | 
            +
            end
         | 
    
        data/specs/examples.rb
    ADDED
    
    | @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            require File.dirname(__FILE__) + '/spec_helper'
         | 
| 2 | 
            +
            require 'open3'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            # This spec checks that the examples are still working.
         | 
| 5 | 
            +
            files = Dir["#{File.dirname(__FILE__)}/../example/*.rb"]
         | 
| 6 | 
            +
            files.delete_if do |file|
         | 
| 7 | 
            +
              file =~ /example_helper.rb/
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            files.each do |example|
         | 
| 11 | 
            +
              describe "Example (#{File.basename(example)})" do
         | 
| 12 | 
            +
                it 'should not output errors' do
         | 
| 13 | 
            +
                  _, _, stderr = Open3.popen3("ruby #{example} 1> /dev/null")
         | 
| 14 | 
            +
                  stderr.gets.should be_nil
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
    
        data/specs/search.rb
    CHANGED
    
    | @@ -205,6 +205,66 @@ describe Gecode::Model, '(optimization search)' do | |
| 205 205 | 
             
                solution.z.value.should == 25
         | 
| 206 206 | 
             
              end
         | 
| 207 207 |  | 
| 208 | 
            +
              it 'should support maximizing singe variables given as symbols' do
         | 
| 209 | 
            +
                solution = SampleOptimizationProblem.new.maximize! :z
         | 
| 210 | 
            +
                solution.should_not be_nil
         | 
| 211 | 
            +
                solution.x.value.should == 5
         | 
| 212 | 
            +
                solution.y.value.should == 5
         | 
| 213 | 
            +
                solution.z.value.should == 25
         | 
| 214 | 
            +
              end
         | 
| 215 | 
            +
              
         | 
| 216 | 
            +
              it 'should support maximizing singe variables given as strings' do
         | 
| 217 | 
            +
                solution = SampleOptimizationProblem.new.maximize! 'z'
         | 
| 218 | 
            +
                solution.should_not be_nil
         | 
| 219 | 
            +
                solution.x.value.should == 5
         | 
| 220 | 
            +
                solution.y.value.should == 5
         | 
| 221 | 
            +
                solution.z.value.should == 25
         | 
| 222 | 
            +
              end
         | 
| 223 | 
            +
              
         | 
| 224 | 
            +
              it 'should raise error if maximize! is given a non-existing method' do
         | 
| 225 | 
            +
                lambda do
         | 
| 226 | 
            +
                  SampleOptimizationProblem.new.maximize! :does_not_exist
         | 
| 227 | 
            +
                end.should raise_error(NameError)
         | 
| 228 | 
            +
              end
         | 
| 229 | 
            +
              
         | 
| 230 | 
            +
              it 'should raise error if maximize! is given a method that does not return an integer variable' do
         | 
| 231 | 
            +
                lambda do
         | 
| 232 | 
            +
                  SampleOptimizationProblem.new.maximize! :object_id
         | 
| 233 | 
            +
                end.should raise_error(ArgumentError)
         | 
| 234 | 
            +
              end
         | 
| 235 | 
            +
              
         | 
| 236 | 
            +
              it 'should support minimizing singe variables given as symbols' do
         | 
| 237 | 
            +
                problem = SampleOptimizationProblem.new
         | 
| 238 | 
            +
                problem.z.must > 2
         | 
| 239 | 
            +
                solution = problem.minimize! :x
         | 
| 240 | 
            +
                solution.should_not be_nil
         | 
| 241 | 
            +
                solution.x.value.should == 1
         | 
| 242 | 
            +
                solution.y.value.should == 3
         | 
| 243 | 
            +
                solution.z.value.should == 3
         | 
| 244 | 
            +
              end
         | 
| 245 | 
            +
              
         | 
| 246 | 
            +
              it 'should support minimizing singe variables given as strings' do
         | 
| 247 | 
            +
                problem = SampleOptimizationProblem.new
         | 
| 248 | 
            +
                problem.z.must > 2
         | 
| 249 | 
            +
                solution = problem.minimize! 'x'
         | 
| 250 | 
            +
                solution.should_not be_nil
         | 
| 251 | 
            +
                solution.x.value.should == 1
         | 
| 252 | 
            +
                solution.y.value.should == 3
         | 
| 253 | 
            +
                solution.z.value.should == 3
         | 
| 254 | 
            +
              end
         | 
| 255 | 
            +
              
         | 
| 256 | 
            +
              it 'should raise error if minimize! is given a non-existing method' do
         | 
| 257 | 
            +
                lambda do
         | 
| 258 | 
            +
                  SampleOptimizationProblem.new.minimize! :does_not_exist
         | 
| 259 | 
            +
                end.should raise_error(NameError)
         | 
| 260 | 
            +
              end
         | 
| 261 | 
            +
              
         | 
| 262 | 
            +
              it 'should raise error if minimize! is given a method that does not return an integer variable' do
         | 
| 263 | 
            +
                lambda do
         | 
| 264 | 
            +
                  SampleOptimizationProblem.new.minimize! :object_id
         | 
| 265 | 
            +
                end.should raise_error(ArgumentError)
         | 
| 266 | 
            +
              end
         | 
| 267 | 
            +
              
         | 
| 208 268 | 
             
              it 'should not be bothered by garbage collecting' do
         | 
| 209 269 | 
             
                # This goes through 400+ spaces.
         | 
| 210 270 | 
             
                solution = SampleOptimizationProblem2.new.optimize! do |model, best_so_far|
         | 
    
        data/specs/set_var.rb
    CHANGED
    
    
    
        data/tasks/distribution.rake
    CHANGED
    
    | @@ -7,6 +7,7 @@ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" | |
| 7 7 | 
             
            PKG_FILE_NAME_WITH_GECODE = "#{PKG_NAME_WITH_GECODE}-#{PKG_VERSION}"
         | 
| 8 8 | 
             
            # The location where the precompiled DLL should be placed.
         | 
| 9 9 | 
             
            DLL_LOCATION = 'lib/gecode.dll'
         | 
| 10 | 
            +
            EXT_DIR = 'ext'
         | 
| 10 11 |  | 
| 11 12 | 
             
            desc 'Generate RDoc'
         | 
| 12 13 | 
             
            rd = Rake::RDocTask.new do |rdoc|
         | 
| @@ -16,14 +17,19 @@ rd = Rake::RDocTask.new do |rdoc| | |
| 16 17 | 
             
              rdoc.rdoc_files.include('README', 'CHANGES', 'LGPL-LICENSE', 'lib/**/*.rb')
         | 
| 17 18 | 
             
            end
         | 
| 18 19 |  | 
| 20 | 
            +
            TMP_DIR = 'doc/tmp/rdoc_dev'
         | 
| 19 21 | 
             
            desc 'Generate RDoc, ignoring nodoc'
         | 
| 20 | 
            -
            Rake::RDocTask.new(:rdoc_dev) do |rdoc|
         | 
| 22 | 
            +
            Rake::RDocTask.new(:rdoc_dev => :prepare_rdoc_dev) do |rdoc|
         | 
| 21 23 | 
             
              rdoc.rdoc_dir = 'doc/output/rdoc_dev'
         | 
| 22 24 | 
             
              rdoc.options << '--title' << 'Gecode/R Developers RDoc' << '--line-numbers' << 
         | 
| 23 25 | 
             
                '--inline-source' << '--accessor' << 'delegate'
         | 
| 24 | 
            -
             | 
| 26 | 
            +
              
         | 
| 27 | 
            +
              rdoc.rdoc_files.include("#{TMP_DIR}/**/*.rb")
         | 
| 28 | 
            +
            end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            desc 'Copies the files that RDoc should parse, removing #:nodoc:'
         | 
| 31 | 
            +
            task :prepare_rdoc_dev do
         | 
| 25 32 | 
             
              # Copy the rdoc and remove all #:nodoc: .
         | 
| 26 | 
            -
              TMP_DIR = 'doc/tmp/rdoc_dev'
         | 
| 27 33 | 
             
              Dir['lib/**/*.rb'].each do |source_name|
         | 
| 28 34 | 
             
                destination_name = source_name.sub('lib', TMP_DIR)
         | 
| 29 35 | 
             
                File.makedirs File.dirname(destination_name)
         | 
| @@ -33,8 +39,6 @@ Rake::RDocTask.new(:rdoc_dev) do |rdoc| | |
| 33 39 | 
             
                end
         | 
| 34 40 | 
             
                destination.close
         | 
| 35 41 | 
             
              end
         | 
| 36 | 
            -
              
         | 
| 37 | 
            -
              rdoc.rdoc_files.include("#{TMP_DIR}/**/*.rb")
         | 
| 38 42 | 
             
            end
         | 
| 39 43 |  | 
| 40 44 | 
             
            spec = Gem::Specification.new do |s|
         | 
| @@ -122,43 +126,55 @@ end | |
| 122 126 | 
             
            desc 'Removes generated distribution files'
         | 
| 123 127 | 
             
            task :clobber do
         | 
| 124 128 | 
             
              rm DLL_LOCATION if File.exists? DLL_LOCATION
         | 
| 129 | 
            +
              FileList[
         | 
| 130 | 
            +
                "#{EXT_DIR}/*.o",
         | 
| 131 | 
            +
                "#{EXT_DIR}/gecode.{cc,hh}",
         | 
| 132 | 
            +
                "#{EXT_DIR}/Makefile",
         | 
| 133 | 
            +
                "#{EXT_DIR}/mkmf.log"
         | 
| 134 | 
            +
              ].to_a.each{ |file| rm file if File.exists? file }
         | 
| 125 135 | 
             
            end
         | 
| 126 136 |  | 
| 127 137 | 
             
            desc 'Publish packages on RubyForge'
         | 
| 128 138 | 
             
            task :publish_packages => [:publish_gecoder_packages, 
         | 
| 129 | 
            -
              :publish_gecoder_with_gecode_packages | 
| 130 | 
            -
             | 
| 139 | 
            +
              :publish_gecoder_with_gecode_packages,
         | 
| 140 | 
            +
              :publish_gecoder_with_gecode_mswin32_packages]
         | 
| 141 | 
            +
             | 
| 142 | 
            +
            # Files included in the vanilla Gecode/R release.
         | 
| 143 | 
            +
            vanilla_release_files = [
         | 
| 144 | 
            +
              "pkg/#{PKG_FILE_NAME}.gem",
         | 
| 145 | 
            +
              "pkg/#{PKG_FILE_NAME}.tgz",
         | 
| 146 | 
            +
              "pkg/#{PKG_FILE_NAME}.zip"
         | 
| 147 | 
            +
            ]
         | 
| 131 148 | 
             
            desc 'Publish Gecode/R packages on RubyForge'
         | 
| 132 | 
            -
            task :publish_gecoder_packages => [:verify_user | 
| 133 | 
            -
              release_files = FileList[
         | 
| 134 | 
            -
                "pkg/#{PKG_FILE_NAME}.gem",
         | 
| 135 | 
            -
                "pkg/#{PKG_FILE_NAME}.tgz",
         | 
| 136 | 
            -
                "pkg/#{PKG_FILE_NAME}.zip"
         | 
| 137 | 
            -
              ]
         | 
| 149 | 
            +
            task :publish_gecoder_packages => [:verify_user] + vanilla_release_files do
         | 
| 138 150 | 
             
              require 'meta_project'
         | 
| 139 151 | 
             
              require 'rake/contrib/xforge'
         | 
| 140 152 |  | 
| 141 153 | 
             
              Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new(PROJECT_NAME)) do |xf|
         | 
| 142 154 | 
             
                xf.user_name = ENV['RUBYFORGE_USER']
         | 
| 143 | 
            -
                xf.files =  | 
| 155 | 
            +
                xf.files = vanilla_release_files.to_a
         | 
| 144 156 | 
             
                xf.release_name = "Gecode/R #{PKG_VERSION}"
         | 
| 157 | 
            +
                xf.package_name = PKG_NAME
         | 
| 145 158 | 
             
              end
         | 
| 146 159 | 
             
            end
         | 
| 147 160 |  | 
| 161 | 
            +
            # Files included in the release with Gecode.
         | 
| 162 | 
            +
            gecode_release_files = [
         | 
| 163 | 
            +
              "pkg/#{PKG_FILE_NAME_WITH_GECODE}.gem",
         | 
| 164 | 
            +
              #"pkg/#{PKG_FILE_NAME_WITH_GECODE}.tgz",
         | 
| 165 | 
            +
              #"pkg/#{PKG_FILE_NAME_WITH_GECODE}.zip",
         | 
| 166 | 
            +
              "pkg/#{PKG_FILE_NAME_WITH_GECODE}-mswin32.gem"
         | 
| 167 | 
            +
            ]
         | 
| 148 168 | 
             
            desc 'Publish Gecode/R with Gecode packages on RubyForge'
         | 
| 149 | 
            -
            task :publish_gecoder_with_gecode_packages =>  | 
| 150 | 
            -
             | 
| 151 | 
            -
                "pkg/#{PKG_FILE_NAME_WITH_GECODE}*.gem",
         | 
| 152 | 
            -
                "pkg/#{PKG_FILE_NAME_WITH_GECODE}*.tgz",
         | 
| 153 | 
            -
                "pkg/#{PKG_FILE_NAME_WITH_GECODE}*.zip"
         | 
| 154 | 
            -
              ]
         | 
| 155 | 
            -
              
         | 
| 169 | 
            +
            task :publish_gecoder_with_gecode_packages => 
         | 
| 170 | 
            +
                [:verify_user] + gecode_release_files do
         | 
| 156 171 | 
             
              require 'meta_project'
         | 
| 157 172 | 
             
              require 'rake/contrib/xforge'
         | 
| 158 173 |  | 
| 159 174 | 
             
              Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new(PROJECT_NAME)) do |xf|
         | 
| 160 175 | 
             
                xf.user_name = ENV['RUBYFORGE_USER']
         | 
| 161 | 
            -
                xf.files =  | 
| 176 | 
            +
                xf.files = gecode_release_files.to_a
         | 
| 162 177 | 
             
                xf.release_name = "Gecode/R with Gecode #{PKG_VERSION}"
         | 
| 178 | 
            +
                xf.package_name = PKG_NAME_WITH_GECODE
         | 
| 163 179 | 
             
              end
         | 
| 164 180 | 
             
            end
         | 
    
        data/tasks/rcov.rake
    CHANGED
    
    | @@ -3,9 +3,10 @@ require 'spec/rake/verify_rcov' | |
| 3 3 |  | 
| 4 4 | 
             
            RCOV_DIR = "#{File.dirname(__FILE__)}/../doc/output/coverage"
         | 
| 5 5 |  | 
| 6 | 
            -
            desc "Run all specs with rcov"
         | 
| 6 | 
            +
            desc "Run all specs (except examples) with rcov"
         | 
| 7 7 | 
             
            Spec::Rake::SpecTask.new(:rcov) do |t|
         | 
| 8 8 | 
             
              t.spec_files = FileList['specs/**/*.rb']
         | 
| 9 | 
            +
              t.spec_files.exclude 'examples.rb'
         | 
| 9 10 | 
             
              t.rcov = true
         | 
| 10 11 | 
             
              t.rcov_opts = ['--exclude examples', '--exclude specs']
         | 
| 11 12 | 
             
              t.rcov_dir = RCOV_DIR
         | 
| @@ -14,4 +15,4 @@ end | |
| 14 15 | 
             
            RCov::VerifyTask.new(:verify_rcov => :rcov) do |t|
         | 
| 15 16 | 
             
              t.threshold = 100.0
         | 
| 16 17 | 
             
              t.index_html = "#{RCOV_DIR}/index.html"
         | 
| 17 | 
            -
            end
         | 
| 18 | 
            +
            end
         | 
    
        data/tasks/specs.rake
    CHANGED
    
    | @@ -3,13 +3,19 @@ require 'spec/rake/spectask' | |
| 3 3 | 
             
            spec_files = FileList['specs/**/*.rb']
         | 
| 4 4 |  | 
| 5 5 | 
             
            desc 'Run all specs'
         | 
| 6 | 
            -
            Spec::Rake::SpecTask.new( | 
| 6 | 
            +
            Spec::Rake::SpecTask.new(:specs) do |t|
         | 
| 7 7 | 
             
              t.libs = ['lib']
         | 
| 8 8 | 
             
              t.spec_files = spec_files
         | 
| 9 9 | 
             
            end
         | 
| 10 10 |  | 
| 11 | 
            +
            desc 'Run specs for the examples'
         | 
| 12 | 
            +
            Spec::Rake::SpecTask.new(:example_specs) do |t|
         | 
| 13 | 
            +
              t.libs = ['lib']
         | 
| 14 | 
            +
              t.spec_files = FileList['specs/examples.rb']
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| 11 17 | 
             
            desc 'Generate an rspec html report'
         | 
| 12 | 
            -
            Spec::Rake::SpecTask.new( | 
| 18 | 
            +
            Spec::Rake::SpecTask.new(:spec_html) do |t|
         | 
| 13 19 | 
             
              t.spec_files = spec_files
         | 
| 14 20 | 
             
              t.spec_opts = ['--format html:doc/output/rspec.html','--backtrace']
         | 
| 15 | 
            -
            end
         | 
| 21 | 
            +
            end
         | 
    
        data/tasks/svn.rake
    CHANGED
    
    | @@ -2,10 +2,13 @@ require 'lib/gecoder/version' | |
| 2 2 |  | 
| 3 3 | 
             
            desc "Tag the release in svn"
         | 
| 4 4 | 
             
            task :tag do
         | 
| 5 | 
            -
               | 
| 6 | 
            -
               | 
| 5 | 
            +
              base_url = `svn info`.match(/Repository Root: (.*)/n)[1]
         | 
| 6 | 
            +
              base_url.gsub!('rubyforge', "#{ENV['RUBYFORGE_USER']}@rubyforge")
         | 
| 7 | 
            +
              from = base_url + '/trunk'
         | 
| 8 | 
            +
              to = base_url + "/tags/gecoder-#{GecodeR::VERSION}"
         | 
| 9 | 
            +
              options = "-m \"Tag release Gecode/R #{GecodeR::VERSION}\""
         | 
| 7 10 |  | 
| 8 11 | 
             
              puts "Creating tag in SVN"
         | 
| 9 | 
            -
              tag_cmd = "svn cp #{from} #{to}  | 
| 12 | 
            +
              tag_cmd = "svn cp #{from} #{to} #{options}"
         | 
| 10 13 | 
             
              `#{tag_cmd}` ; raise "ERROR: #{tag_cmd}" unless $? == 0
         | 
| 11 14 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -3,8 +3,8 @@ rubygems_version: 0.9.4 | |
| 3 3 | 
             
            specification_version: 1
         | 
| 4 4 | 
             
            name: gecoder-with-gecode
         | 
| 5 5 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 6 | 
            -
              version: 0.8. | 
| 7 | 
            -
            date: 2008-04- | 
| 6 | 
            +
              version: 0.8.1
         | 
| 7 | 
            +
            date: 2008-04-20 00:00:00 +02:00
         | 
| 8 8 | 
             
            summary: Ruby interface to Gecode, an environment for constraint programming.
         | 
| 9 9 | 
             
            require_paths: 
         | 
| 10 10 | 
             
            - lib
         | 
| @@ -34,7 +34,8 @@ files: | |
| 34 34 | 
             
            - COPYING
         | 
| 35 35 | 
             
            - README
         | 
| 36 36 | 
             
            - LGPL-LICENSE
         | 
| 37 | 
            -
            - lib/gecoder/interface/constraints/bool_enum/ | 
| 37 | 
            +
            - lib/gecoder/interface/constraints/bool_enum/extensional.rb
         | 
| 38 | 
            +
            - lib/gecoder/interface/constraints/bool_enum/relation.rb
         | 
| 38 39 | 
             
            - lib/gecoder/interface/constraints/set_enum/operation.rb
         | 
| 39 40 | 
             
            - lib/gecoder/interface/constraints/set_enum/distinct.rb
         | 
| 40 41 | 
             
            - lib/gecoder/interface/constraints/set_enum/selection.rb
         | 
| @@ -56,6 +57,7 @@ files: | |
| 56 57 | 
             
            - lib/gecoder/interface/constraints/int_enum/count.rb
         | 
| 57 58 | 
             
            - lib/gecoder/interface/constraints/int_enum/arithmetic.rb
         | 
| 58 59 | 
             
            - lib/gecoder/interface/constraints/int_enum/element.rb
         | 
| 60 | 
            +
            - lib/gecoder/interface/constraints/int_enum/extensional.rb
         | 
| 59 61 | 
             
            - lib/gecoder/interface/constraints/int_enum_constraints.rb
         | 
| 60 62 | 
             
            - lib/gecoder/interface/constraints/bool_enum_constraints.rb
         | 
| 61 63 | 
             
            - lib/gecoder/interface/constraints/set_enum_constraints.rb
         | 
| @@ -156,7 +158,6 @@ files: | |
| 156 158 | 
             
            - tasks/dependencies.txt
         | 
| 157 159 | 
             
            - specs/constraints
         | 
| 158 160 | 
             
            - specs/constraints/boolean.rb
         | 
| 159 | 
            -
            - specs/constraints/bool_enum.rb
         | 
| 160 161 | 
             
            - specs/constraints/int_domain.rb
         | 
| 161 162 | 
             
            - specs/constraints/distinct.rb
         | 
| 162 163 | 
             
            - specs/constraints/set_domain.rb
         | 
| @@ -176,6 +177,8 @@ files: | |
| 176 177 | 
             
            - specs/constraints/channel.rb
         | 
| 177 178 | 
             
            - specs/constraints/linear.rb
         | 
| 178 179 | 
             
            - specs/constraints/set_operation.rb
         | 
| 180 | 
            +
            - specs/constraints/extensional.rb
         | 
| 181 | 
            +
            - specs/constraints/bool_enum_relation.rb
         | 
| 179 182 | 
             
            - specs/branch.rb
         | 
| 180 183 | 
             
            - specs/model.rb
         | 
| 181 184 | 
             
            - specs/binding_changes.rb
         | 
| @@ -188,6 +191,7 @@ files: | |
| 188 191 | 
             
            - specs/enum_matrix.rb
         | 
| 189 192 | 
             
            - specs/spec_helper.rb
         | 
| 190 193 | 
             
            - specs/distribution.rb
         | 
| 194 | 
            +
            - specs/examples.rb
         | 
| 191 195 | 
             
            - ext/missing.cpp
         | 
| 192 196 | 
             
            - ext/vararray.cpp
         | 
| 193 197 | 
             
            - ext/missing.h
         | 
| @@ -785,7 +789,6 @@ files: | |
| 785 789 | 
             
            - ext/gecode-2.1.1/install-sh
         | 
| 786 790 | 
             
            test_files: 
         | 
| 787 791 | 
             
            - specs/constraints/boolean.rb
         | 
| 788 | 
            -
            - specs/constraints/bool_enum.rb
         | 
| 789 792 | 
             
            - specs/constraints/int_domain.rb
         | 
| 790 793 | 
             
            - specs/constraints/distinct.rb
         | 
| 791 794 | 
             
            - specs/constraints/set_domain.rb
         | 
| @@ -805,6 +808,8 @@ test_files: | |
| 805 808 | 
             
            - specs/constraints/channel.rb
         | 
| 806 809 | 
             
            - specs/constraints/linear.rb
         | 
| 807 810 | 
             
            - specs/constraints/set_operation.rb
         | 
| 811 | 
            +
            - specs/constraints/extensional.rb
         | 
| 812 | 
            +
            - specs/constraints/bool_enum_relation.rb
         | 
| 808 813 | 
             
            - specs/branch.rb
         | 
| 809 814 | 
             
            - specs/model.rb
         | 
| 810 815 | 
             
            - specs/binding_changes.rb
         | 
| @@ -817,6 +822,7 @@ test_files: | |
| 817 822 | 
             
            - specs/enum_matrix.rb
         | 
| 818 823 | 
             
            - specs/spec_helper.rb
         | 
| 819 824 | 
             
            - specs/distribution.rb
         | 
| 825 | 
            +
            - specs/examples.rb
         | 
| 820 826 | 
             
            rdoc_options: 
         | 
| 821 827 | 
             
            - --title
         | 
| 822 828 | 
             
            - Gecode/R
         | 
| @@ -830,7 +836,8 @@ extra_rdoc_files: | |
| 830 836 | 
             
            - README
         | 
| 831 837 | 
             
            - CHANGES
         | 
| 832 838 | 
             
            - LGPL-LICENSE
         | 
| 833 | 
            -
            - lib/gecoder/interface/constraints/bool_enum/ | 
| 839 | 
            +
            - lib/gecoder/interface/constraints/bool_enum/extensional.rb
         | 
| 840 | 
            +
            - lib/gecoder/interface/constraints/bool_enum/relation.rb
         | 
| 834 841 | 
             
            - lib/gecoder/interface/constraints/set_enum/operation.rb
         | 
| 835 842 | 
             
            - lib/gecoder/interface/constraints/set_enum/distinct.rb
         | 
| 836 843 | 
             
            - lib/gecoder/interface/constraints/set_enum/selection.rb
         | 
| @@ -852,6 +859,7 @@ extra_rdoc_files: | |
| 852 859 | 
             
            - lib/gecoder/interface/constraints/int_enum/count.rb
         | 
| 853 860 | 
             
            - lib/gecoder/interface/constraints/int_enum/arithmetic.rb
         | 
| 854 861 | 
             
            - lib/gecoder/interface/constraints/int_enum/element.rb
         | 
| 862 | 
            +
            - lib/gecoder/interface/constraints/int_enum/extensional.rb
         | 
| 855 863 | 
             
            - lib/gecoder/interface/constraints/int_enum_constraints.rb
         | 
| 856 864 | 
             
            - lib/gecoder/interface/constraints/bool_enum_constraints.rb
         | 
| 857 865 | 
             
            - lib/gecoder/interface/constraints/set_enum_constraints.rb
         |