gecoder 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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