lib/gecoder/interface/branch.rb in gecoder-0.5.0 vs lib/gecoder/interface/branch.rb in gecoder-0.6.0

- old
+ new

@@ -1,12 +1,12 @@ module Gecode class Model private - # Maps the names of the supported variable branch strategies to the - # corresponding constant in Gecode. - BRANCH_VAR_CONSTANTS = { + # Maps the names of the supported variable branch strategies for integer and + # booleans to the corresponding constant in Gecode. + BRANCH_INT_VAR_CONSTANTS = { :none => Gecode::Raw::BVAR_NONE, :smallest_min => Gecode::Raw::BVAR_MIN_MIN, :largest_min => Gecode::Raw::BVAR_MIN_MAX, :smallest_max => Gecode::Raw::BVAR_MAX_MIN, :largest_max => Gecode::Raw::BVAR_MAX_MAX, @@ -17,30 +17,46 @@ :smallest_min_regret => Gecode::Raw::BVAR_REGRET_MIN_MIN, :largest_min_regret => Gecode::Raw::BVAR_REGRET_MIN_MAX, :smallest_max_regret => Gecode::Raw::BVAR_REGRET_MAX_MIN, :largest_max_regret => Gecode::Raw::BVAR_REGRET_MAX_MAX } + # Maps the names of the supported variable branch strategies for sets to + # the corresponding constant in Gecode. + BRANCH_SET_VAR_CONSTANTS = { + :none => Gecode::Raw::SETBVAR_NONE, + :smallest_cardinality => Gecode::Raw::SETBVAR_MIN_CARD, + :largest_cardinality => Gecode::Raw::SETBVAR_MAX_CARD, + :smallest_unknown => Gecode::Raw::SETBVAR_MIN_UNKNOWN_ELEM, + :largest_unknown => Gecode::Raw::SETBVAR_MAX_UNKNOWN_ELEM + } - # Maps the names of the supported value branch strategies to the - # corresponding constant in Gecode. - BRANCH_VALUE_CONSTANTS = { + # Maps the names of the supported value branch strategies for integers and + # booleans to the corresponding constant in Gecode. + BRANCH_INT_VALUE_CONSTANTS = { :min => Gecode::Raw::BVAL_MIN, :med => Gecode::Raw::BVAL_MED, :max => Gecode::Raw::BVAL_MAX, :split_min => Gecode::Raw::BVAL_SPLIT_MIN, :split_max => Gecode::Raw::BVAL_SPLIT_MAX } + # Maps the names of the supported value branch strategies for sets to the + # corresponding constant in Gecode. + BRANCH_SET_VALUE_CONSTANTS = { + :min => Gecode::Raw::SETBVAL_MIN, + :max => Gecode::Raw::SETBVAL_MAX + } public # Specifies which variables that should be branched on. One can optionally # also select which of the variables that should be used first with the # :variable option and which value in that variable's domain that should be # used with the :value option. If nothing is specified then :variable uses # :none and value uses :min. # - # The following values can be used with :variable + # The following values can be used with :variable for integer and boolean + # enums: # [:none] The first unassigned variable. # [:smallest_min] The one with the smallest minimum. # [:largest_min] The one with the largest minimum. # [:smallest_max] The one with the smallest maximum. # [:largest_max] The one with the largest maximum. @@ -69,34 +85,69 @@ # [:largest_max_regret] The one with the largest max-regret. The # max-regret of a variable is the difference between # the largest and second-largest value still in # the domain. # - # The following values can be used with :value + # The following values can be used with :value for integer and boolean + # enums: # [:min] Selects the smallest value. # [:med] Select the median value. # [:max] Selects the largest vale # [:split_min] Selects the lower half of the domain. # [:split_max] Selects the upper half of the domain. + # + # The following values can be used with :variable for set enums: + # [:none] The first unassigned set. + # [:smallest_cardinality] The one with the smallest cardinality. + # [:largest_cardinality] The one with the largest cardinality. + # [:smallest_unknown] The one with the smallest number of unknown + # elements + # [:largest_unknown] The one with the largest number of unknown + # elements + # + # The following values can be used with :value set enums: + # enums: + # [:min] Selects the smallest value in the unknown part of the set. + # [:max] Selects the largest value in the unknown part of the set. def branch_on(variables, options = {}) + if variables.respond_to? :to_int_var_array or + variables.respond_to? :to_bool_var_array + add_branch(variables, options, BRANCH_INT_VAR_CONSTANTS, + BRANCH_INT_VALUE_CONSTANTS) + elsif variables.respond_to? :to_set_var_array + add_branch(variables, options, BRANCH_SET_VAR_CONSTANTS, + BRANCH_SET_VALUE_CONSTANTS) + else + raise TypeError, "Unknown type of variable enum #{variables.class}." + end + end + + private + + # Adds a branching selection for the specified variable with the specified + # options. The hashes are used to decode the options into Gecode's + # constants. + def add_branch(variables, options, branch_var_hash, branch_value_hash) # Extract optional arguments. var_strat = options.delete(:variable) || :none val_strat = options.delete(:value) || :min - + # Check that the options are correct. unless options.empty? raise ArgumentError, 'Unknown branching option given: ' + options.keys.join(', ') end - unless BRANCH_VAR_CONSTANTS.include? var_strat + unless branch_var_hash.include? var_strat raise ArgumentError, "Unknown variable selection strategy: #{var_strat}" end - unless BRANCH_VALUE_CONSTANTS.include? val_strat + unless branch_value_hash.include? val_strat raise ArgumentError, "Unknown value selection strategy: #{val_strat}" end - # Add the branching. - Gecode::Raw.branch(active_space, variables.to_var_array, - BRANCH_VAR_CONSTANTS[var_strat], BRANCH_VALUE_CONSTANTS[val_strat]) + # Add the branching as a gecode interaction. + add_interaction do + Gecode::Raw.branch(active_space, variables.to_var_array, + branch_var_hash[var_strat], branch_value_hash[val_strat]) + end end end end \ No newline at end of file