gecoder 0.2.0

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.
Files changed (75) hide show
  1. data/COPYING +17 -0
  2. data/LGPL-LICENSE +458 -0
  3. data/README +20 -0
  4. data/Rakefile +6 -0
  5. data/ext/extconf.rb +29 -0
  6. data/ext/missing.cpp +295 -0
  7. data/ext/missing.h +116 -0
  8. data/ext/vararray.cpp +312 -0
  9. data/ext/vararray.h +146 -0
  10. data/lib/gecoder.rb +4 -0
  11. data/lib/gecoder/bindings.rb +7 -0
  12. data/lib/gecoder/bindings/bindings.rb +2055 -0
  13. data/lib/gecoder/interface.rb +6 -0
  14. data/lib/gecoder/interface/binding_changes.rb +111 -0
  15. data/lib/gecoder/interface/branch.rb +102 -0
  16. data/lib/gecoder/interface/constraints.rb +10 -0
  17. data/lib/gecoder/interface/constraints/distinct.rb +15 -0
  18. data/lib/gecoder/interface/constraints/linear.rb +158 -0
  19. data/lib/gecoder/interface/constraints/relation.rb +76 -0
  20. data/lib/gecoder/interface/enum_wrapper.rb +64 -0
  21. data/lib/gecoder/interface/model.rb +130 -0
  22. data/lib/gecoder/interface/search.rb +23 -0
  23. data/vendor/rust/README +28 -0
  24. data/vendor/rust/bin/cxxgenerator.rb +93 -0
  25. data/vendor/rust/include/rust_checks.hh +115 -0
  26. data/vendor/rust/include/rust_conversions.hh +103 -0
  27. data/vendor/rust/rust.rb +67 -0
  28. data/vendor/rust/rust/attribute.rb +51 -0
  29. data/vendor/rust/rust/bindings.rb +172 -0
  30. data/vendor/rust/rust/class.rb +334 -0
  31. data/vendor/rust/rust/constants.rb +48 -0
  32. data/vendor/rust/rust/container.rb +110 -0
  33. data/vendor/rust/rust/cppifaceparser.rb +129 -0
  34. data/vendor/rust/rust/cwrapper.rb +72 -0
  35. data/vendor/rust/rust/cxxclass.rb +98 -0
  36. data/vendor/rust/rust/element.rb +81 -0
  37. data/vendor/rust/rust/enum.rb +63 -0
  38. data/vendor/rust/rust/function.rb +407 -0
  39. data/vendor/rust/rust/namespace.rb +61 -0
  40. data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
  41. data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
  42. data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
  43. data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
  44. data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
  45. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
  46. data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
  47. data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
  48. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +91 -0
  49. data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
  50. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +12 -0
  51. data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
  52. data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
  53. data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
  54. data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
  55. data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
  56. data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
  57. data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
  58. data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
  59. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +5 -0
  60. data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
  61. data/vendor/rust/rust/type.rb +98 -0
  62. data/vendor/rust/test/Makefile +4 -0
  63. data/vendor/rust/test/constants.rb +35 -0
  64. data/vendor/rust/test/cppclass.cc +40 -0
  65. data/vendor/rust/test/cppclass.hh +63 -0
  66. data/vendor/rust/test/cppclass.rb +59 -0
  67. data/vendor/rust/test/cwrapper.c +74 -0
  68. data/vendor/rust/test/cwrapper.h +41 -0
  69. data/vendor/rust/test/cwrapper.rb +56 -0
  70. data/vendor/rust/test/dummyclass.hh +31 -0
  71. data/vendor/rust/test/lib/extension-test.rb +98 -0
  72. data/vendor/rust/test/test-constants.rb +43 -0
  73. data/vendor/rust/test/test-cppclass.rb +82 -0
  74. data/vendor/rust/test/test-cwrapper.rb +77 -0
  75. metadata +144 -0
@@ -0,0 +1,6 @@
1
+ require 'gecoder/interface/binding_changes'
2
+ require 'gecoder/interface/model'
3
+ require 'gecoder/interface/search'
4
+ require 'gecoder/interface/constraints'
5
+ require 'gecoder/interface/enum_wrapper'
6
+ require 'gecoder/interface/branch'
@@ -0,0 +1,111 @@
1
+ # This file adds a small layer on top of the bindings. It alters the allocation
2
+ # of variables so that a single array is allocated in each space which is then
3
+ # used to store variable. The variables themselves are not directly returned,
4
+ # rather they are represented as the index in that store, which allows the
5
+ # variable to be retrieved back given a space.
6
+ #
7
+ # This layer should be moved to the C++ side instead when possible for better
8
+ # performance.
9
+ module Gecode::Raw
10
+ class Space
11
+ # Creates the specified number of integer variables in the store. Returns
12
+ # the indices with which they can then be accessed using int_var.
13
+ def new_int_vars(min, max, count = 1)
14
+ int_var_store.new_vars(min, max, count)
15
+ end
16
+
17
+ # Gets the int variable with the specified index, nil if none exists.
18
+ def int_var(index)
19
+ int_var_store[index]
20
+ end
21
+
22
+ private
23
+
24
+ # Retrieves the store used for integer variables. Creates one if none
25
+ # exists.
26
+ def int_var_store
27
+ if @int_var_store.nil?
28
+ @int_var_store = Gecode::Raw::IntVarStore.new(self)
29
+ end
30
+ return @int_var_store
31
+ end
32
+ end
33
+
34
+ # A store in which int variables are created and stored.
35
+ class IntVarStore
36
+ # Design note: The store used to double its size when it needed to grow
37
+ # leaving unallocated slots (in rev 16). This was changed to only growing
38
+ # the amount of space needed because the additional information about which
39
+ # slot is the next unallocated one could not be encoded without changes to
40
+ # the bindings (and without that information we can not deduce the store
41
+ # from the new copy of space). So for additional performance the bindings
42
+ # should grow the array more than needed (when this is moved to the bindings).
43
+
44
+ private
45
+
46
+ # A string that identifies the array used by the store.
47
+ ARRAY_IDENTIFIER = 'int_array'
48
+
49
+ public
50
+
51
+ # Creates a store for the specified space with the specified capacit.
52
+ def initialize(space)
53
+ @var_array = space.int_var_array(ARRAY_IDENTIFIER)
54
+ if @var_array.nil?
55
+ # Create a new one.
56
+ @var_array = Gecode::Raw::IntVarArray.new(space, 0)
57
+ space.own(@var_array, ARRAY_IDENTIFIER)
58
+ end
59
+
60
+ @size = @var_array.size
61
+ @next_index = @size
62
+ @space = space
63
+ end
64
+
65
+ # Creates the specified number of new int variables with the specified
66
+ # range as domain. Returns the indices of the created variables as an array.
67
+ def new_vars(min, max, count = 1)
68
+ grow(@next_index + count) # See the design note for more information.
69
+ count.times do |i|
70
+ @var_array[@next_index] = Gecode::Raw::IntVar.new(@space,
71
+ min, max)
72
+ @next_index += 1
73
+ end
74
+
75
+ ((@next_index - count)...@next_index).to_a
76
+ end
77
+
78
+ # Returns the int var with the specified index, nil if none exists.
79
+ def [](index)
80
+ if index < 0 or index >= @next_index
81
+ return nil
82
+ end
83
+ return @var_array.at(index)
84
+ end
85
+
86
+ private
87
+
88
+ # Grows the store to the new size.
89
+ def grow(new_size)
90
+ if new_size <= @size
91
+ raise ArgumentError, 'New size must be larger than the old one.'
92
+ end
93
+
94
+ new_array = Gecode::Raw::IntVarArray.new(@space, new_size)
95
+ @var_array.size.times do |i|
96
+ new_array[i] = @var_array[i]
97
+ end
98
+ @space.own(new_array, ARRAY_IDENTIFIER)
99
+ @var_array = new_array
100
+ @size = new_size
101
+ end
102
+ end
103
+
104
+ class IntVar
105
+ # Aliases to make method-names more ruby-like.
106
+ alias_method :assigned?, :assigned
107
+ alias_method :in?, :in
108
+ alias_method :range?, :range
109
+ end
110
+ end
111
+
@@ -0,0 +1,102 @@
1
+ module Gecode
2
+ class Model
3
+ private
4
+
5
+ # Maps the names of the supported variable branch strategies to the
6
+ # corresponding constant in Gecode.
7
+ BRANCH_VAR_CONSTANTS = {
8
+ :none => Gecode::Raw::BVAR_NONE,
9
+ :smallest_min => Gecode::Raw::BVAR_MIN_MIN,
10
+ :largest_min => Gecode::Raw::BVAR_MIN_MAX,
11
+ :smallest_max => Gecode::Raw::BVAR_MAX_MIN,
12
+ :largest_max => Gecode::Raw::BVAR_MAX_MAX,
13
+ :smallest_size => Gecode::Raw::BVAR_SIZE_MIN,
14
+ :largest_size => Gecode::Raw::BVAR_SIZE_MAX,
15
+ :smallest_degree => Gecode::Raw::BVAR_DEGREE_MIN,
16
+ :largest_degree => Gecode::Raw::BVAR_DEGREE_MAX,
17
+ :smallest_min_regret => Gecode::Raw::BVAR_REGRET_MIN_MIN,
18
+ :largest_min_regret => Gecode::Raw::BVAR_REGRET_MIN_MAX,
19
+ :smallest_max_regret => Gecode::Raw::BVAR_REGRET_MAX_MIN,
20
+ :largest_max_regret => Gecode::Raw::BVAR_REGRET_MAX_MAX
21
+ }
22
+
23
+ # Maps the names of the supported value branch strategies to the
24
+ # corresponding constant in Gecode.
25
+ BRANCH_VALUE_CONSTANTS = {
26
+ :min => Gecode::Raw::BVAL_MIN,
27
+ :med => Gecode::Raw::BVAL_MED,
28
+ :max => Gecode::Raw::BVAL_MAX,
29
+ :split_min => Gecode::Raw::BVAL_SPLIT_MIN,
30
+ :split_max => Gecode::Raw::BVAL_SPLIT_MAX
31
+ }
32
+
33
+ public
34
+
35
+ # Specifies which variables that should be branched on. One can optionally
36
+ # also select which of the variables that should be used first with the
37
+ # :variable option and which value in that variable's domain that should be
38
+ # used with the :value option. If nothing is specified then :variable uses
39
+ # :none and value uses :min.
40
+ #
41
+ # The following values can be used with :variable
42
+ # [:none] The first unassigned variable.
43
+ # [:smallest_min] The one with the smallest minimum.
44
+ # [:largest_min] The one with the largest minimum.
45
+ # [:smallest_max] The one with the smallest maximum.
46
+ # [:largest_max] The one with the largest maximum.
47
+ # [:smallest_size] The one with the smallest size.
48
+ # [:largest_size] The one with the larges size.
49
+ # [:smallest_degree] The one with the smallest degree. The degree of a
50
+ # variable is defined as the number of dependant
51
+ # propagators. In case of ties, choose the variable
52
+ # with smallest domain.
53
+ # [:largest_degree] The one with the largest degree. The degree of a
54
+ # variable is defined as the number of dependant
55
+ # propagators. In case of ties, choose the variable
56
+ # with smallest domain.
57
+ # [:smallest_min_regret] The one with the smallest min-regret. The
58
+ # min-regret of a variable is the difference between
59
+ # the smallest and second-smallest value still in
60
+ # the domain.
61
+ # [:largest_min_regret] The one with the largest min-regret. The
62
+ # min-regret of a variable is the difference between
63
+ # the smallest and second-smallest value still in
64
+ # the domain.
65
+ # [:smallest_max_regret] The one with the smallest max-regret The
66
+ # max-regret of a variable is the difference between
67
+ # the largest and second-largest value still in
68
+ # the domain.
69
+ # [:largest_max_regret] The one with the largest max-regret. The
70
+ # max-regret of a variable is the difference between
71
+ # the largest and second-largest value still in
72
+ # the domain.
73
+ #
74
+ # The following values can be used with :value
75
+ # [:min] Selects the smallest value.
76
+ # [:med] Select the median value.
77
+ # [:max] Selects the largest vale
78
+ # [:split_min] Selects the lower half of the domain.
79
+ # [:split_max] Selects the upper half of the domain.
80
+ def branch_on(variables, options = {})
81
+ # Extract optional arguments.
82
+ var_strat = options.delete(:variable) || :none
83
+ val_strat = options.delete(:value) || :min
84
+
85
+ # Check that the options are correct.
86
+ unless options.empty?
87
+ raise ArgumentError, 'Unknown branching option given: ' +
88
+ options.keys.join(', ')
89
+ end
90
+ unless BRANCH_VAR_CONSTANTS.include? var_strat
91
+ raise ArgumentError, "Unknown variable selection strategy: #{var_strat}"
92
+ end
93
+ unless BRANCH_VALUE_CONSTANTS.include? val_strat
94
+ raise ArgumentError, "Unknown value selection strategy: #{val_strat}"
95
+ end
96
+
97
+ # Add the branching.
98
+ Gecode::Raw.branch(active_space, variables.to_int_var_array,
99
+ BRANCH_VAR_CONSTANTS[var_strat], BRANCH_VALUE_CONSTANTS[val_strat])
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,10 @@
1
+ require 'gecoder/interface/constraints/relation'
2
+ require 'gecoder/interface/constraints/distinct'
3
+ require 'gecoder/interface/constraints/linear'
4
+
5
+ module Gecode
6
+ # An error signaling that the constraint specified is missing (e.g. one tried
7
+ # to negate a constraint, but no negated form is implemented).
8
+ class MissingConstraintError < StandardError
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ module Gecode
2
+ class IntVarEnumConstraintExpression
3
+ # Posts a distinct constraint on the variables in the enum.
4
+ def distinct
5
+ if @negate
6
+ # The best we could implement it as from here would be a bunch of
7
+ # reified pairwise equality constraints.
8
+ raise Gecode::MissingConstraintError, 'A negated distinct has not ' +
9
+ 'been implemented.'
10
+ end
11
+
12
+ Gecode::Raw::distinct(@space, @var_array, Gecode::Raw::ICL_DEF)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,158 @@
1
+ module Gecode
2
+ class FreeIntVar
3
+ # Creates a linear expression where the int variables are summed.
4
+ def +(var)
5
+ Gecode::LinearConstraintExpressionNode.new(self, active_space) + var
6
+ end
7
+
8
+ # Creates a linear expression where the int variable is multiplied with
9
+ # a constant integer.
10
+ def *(int)
11
+ Gecode::LinearConstraintExpressionNode.new(self, active_space) * int
12
+ end
13
+
14
+ # Creates a linear expression where the specified variable is subtracted
15
+ # from this one.
16
+ def -(var)
17
+ Gecode::LinearConstraintExpressionNode.new(self, active_space) - var
18
+ end
19
+ end
20
+
21
+ module LinearConstraintHelper
22
+ OPERATION_TYPES = [:+, :-, :*]
23
+
24
+ # Define methods for the available operations.
25
+ OPERATION_TYPES.each do |name|
26
+ module_eval <<-"end_code"
27
+ def #{name}(expression)
28
+ unless expression.kind_of? Gecode::LinearConstraintExpressionTree
29
+ expression = Gecode::LinearConstraintExpressionNode.new(expression)
30
+ end
31
+ Gecode::LinearConstraintExpressionTree.new(self, expression, :#{name})
32
+ end
33
+ end_code
34
+ end
35
+
36
+ # Specifies that a constraint must hold for the linear expression.
37
+ def must
38
+ Gecode::LinearConstraintExpression.new(self)
39
+ end
40
+
41
+ # Specifies that the negation of a constraint must hold for the linear
42
+ # expression.
43
+ def must_not
44
+ Gecode::LinearConstraintExpression.new(self, true)
45
+ end
46
+ end
47
+
48
+ # Describes a linear constraint that starts with a linear expression followed
49
+ # by must or must_not.
50
+ class LinearConstraintExpressionTree
51
+ include Gecode::LinearConstraintHelper
52
+
53
+ # Constructs a new expression with the specified variable
54
+ def initialize(left_node, right_node, operation)
55
+ @left = left_node
56
+ @right = right_node
57
+ @operation = operation
58
+ end
59
+
60
+ # Converts the linear expression to an instance of
61
+ # Gecode::Raw::MiniModel::LinExpr
62
+ def to_minimodel_lin_exp
63
+ @left.to_minimodel_lin_exp.send(@operation, @right.to_minimodel_lin_exp)
64
+ end
65
+
66
+ # Fetches the space that the expression's variables is in.
67
+ def space
68
+ @left.space || @right.space
69
+ end
70
+ end
71
+
72
+ # Describes a single node in a linear constrain expression.
73
+ class LinearConstraintExpressionNode
74
+ include Gecode::LinearConstraintHelper
75
+
76
+ attr :space
77
+
78
+ def initialize(value, space = nil)
79
+ @value = value
80
+ @space = space
81
+ end
82
+
83
+ # Converts the linear expression to an instance of
84
+ # Gecode::Raw::MiniModel::LinExpr
85
+ def to_minimodel_lin_exp
86
+ expression = @value
87
+ if expression.kind_of? FreeIntVar
88
+ # Minimodel requires that we do this first.
89
+ expression = expression.bind * 1
90
+ end
91
+ expression
92
+ end
93
+ end
94
+
95
+ # Describes a linear constraint expression that starts with a linear
96
+ # expression followed by must or must_not.
97
+ class LinearConstraintExpression
98
+ # TODO: this is awfully similar to IntVarConstrainExpression. There should
99
+ # be some way to combine them.
100
+
101
+ # Maps the names of the methods to the corresponding integer relation
102
+ # type in Gecode.
103
+ RELATION_TYPES = {
104
+ :== => Gecode::Raw::IRT_EQ,
105
+ :<= => Gecode::Raw::IRT_LQ,
106
+ :< => Gecode::Raw::IRT_LE,
107
+ :>= => Gecode::Raw::IRT_GQ,
108
+ :> => Gecode::Raw::IRT_GR }
109
+ # The same as above, but negated.
110
+ NEGATED_RELATION_TYPES = {
111
+ :== => Gecode::Raw::IRT_NQ,
112
+ :<= => Gecode::Raw::IRT_GR,
113
+ :< => Gecode::Raw::IRT_GQ,
114
+ :>= => Gecode::Raw::IRT_LE,
115
+ :> => Gecode::Raw::IRT_LQ
116
+ }
117
+
118
+ # Constructs the expression with the specified left hand side. The
119
+ # expression can optionally be negated.
120
+ def initialize(left_hand_side, negate = false)
121
+ @lhs = left_hand_side
122
+ unless negate
123
+ @method_relations = RELATION_TYPES
124
+ else
125
+ @method_relations = NEGATED_RELATION_TYPES
126
+ end
127
+ end
128
+
129
+ RELATION_TYPES.each_key do |name|
130
+ module_eval <<-"end_code"
131
+ def #{name}(expression)
132
+ post_relation_constraint(@method_relations[:#{name}], expression)
133
+ end
134
+ end_code
135
+ end
136
+
137
+ private
138
+
139
+ # Places the relation constraint corresponding to the specified (integer)
140
+ # relation type (as specified by Gecode) in relation to the specifed
141
+ # element.
142
+ #
143
+ # Raises TypeError if the element is of a type that doesn't allow a relation
144
+ # to be specified.
145
+ def post_relation_constraint(relation_type, right_hand_side)
146
+ if right_hand_side.respond_to? :to_minimodel_lin_exp
147
+ right_hand_side = right_hand_side.to_minimodel_lin_exp
148
+ elsif right_hand_side.kind_of? Gecode::FreeIntVar
149
+ right_hand_side = right_hand_side.bind * 1
150
+ elsif not right_hand_side.kind_of? Fixnum
151
+ raise TypeError, 'Invalid right hand side of linear equation.'
152
+ end
153
+
154
+ (@lhs.to_minimodel_lin_exp - right_hand_side).post(@lhs.space,
155
+ relation_type, Gecode::Raw::ICL_DEF)
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,76 @@
1
+ module Gecode
2
+ class FreeIntVar
3
+ # Specifies that a constraint must hold for the integer variable.
4
+ def must
5
+ Gecode::IntVarConstraintExpression.new(active_space, self.bind)
6
+ end
7
+
8
+ # Specifies that the negation of a constraint must hold for the integer
9
+ # variable.
10
+ def must_not
11
+ Gecode::IntVarConstraintExpression.new(active_space, self.bind, true)
12
+ end
13
+ end
14
+
15
+ # Describes a constraint expression that starts with a single integer variable
16
+ # followed by must or must_not.
17
+ class IntVarConstraintExpression
18
+ private
19
+
20
+ # Maps the names of the methods to the corresponding integer relation
21
+ # type in Gecode.
22
+ RELATION_TYPES = {
23
+ :== => Gecode::Raw::IRT_EQ,
24
+ :<= => Gecode::Raw::IRT_LQ,
25
+ :< => Gecode::Raw::IRT_LE,
26
+ :>= => Gecode::Raw::IRT_GQ,
27
+ :> => Gecode::Raw::IRT_GR }
28
+ # The same as above, but negated.
29
+ NEGATED_RELATION_TYPES = {
30
+ :== => Gecode::Raw::IRT_NQ,
31
+ :<= => Gecode::Raw::IRT_GR,
32
+ :< => Gecode::Raw::IRT_GQ,
33
+ :>= => Gecode::Raw::IRT_LE,
34
+ :> => Gecode::Raw::IRT_LQ
35
+ }
36
+
37
+ public
38
+
39
+ # Constructs a new expression with the specified space and (bound) variable
40
+ # as source. The expression can optionally be negated.
41
+ def initialize(space, var, negate = false)
42
+ @space = space
43
+ @var = var
44
+ unless negate
45
+ @method_relations = RELATION_TYPES
46
+ else
47
+ @method_relations = NEGATED_RELATION_TYPES
48
+ end
49
+ end
50
+
51
+ RELATION_TYPES.each_key do |name|
52
+ module_eval <<-"end_code"
53
+ def #{name}(element)
54
+ post_relation_constraint(@method_relations[:#{name}], element)
55
+ end
56
+ end_code
57
+ end
58
+
59
+ private
60
+
61
+ # Places the relation constraint corresponding to the specified (integer)
62
+ # relation type (as specified by Gecode) in relation to the specifed
63
+ # element.
64
+ #
65
+ # Raises TypeError if the element is of a type that doesn't allow a relation
66
+ # to be specified.
67
+ def post_relation_constraint(relation_type, element)
68
+ if element.kind_of? Fixnum
69
+ Gecode::Raw::rel(@space, @var, relation_type, element,
70
+ Gecode::Raw::ICL_DEF)
71
+ else
72
+ raise TypeError, 'Relations only allow Fixnum.'
73
+ end
74
+ end
75
+ end
76
+ end