gecoder-with-gecode 0.9.0-x86-mswin32-60

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 (203) hide show
  1. data/CHANGES +137 -0
  2. data/COPYING +17 -0
  3. data/LGPL-LICENSE +458 -0
  4. data/README +58 -0
  5. data/Rakefile +14 -0
  6. data/example/equation_system.rb +15 -0
  7. data/example/example_helper.rb +1 -0
  8. data/example/magic_sequence.rb +43 -0
  9. data/example/money.rb +36 -0
  10. data/example/queens.rb +42 -0
  11. data/example/send_more_money.rb +43 -0
  12. data/example/send_most_money.rb +58 -0
  13. data/example/square_tiling.rb +84 -0
  14. data/example/sudoku-set.rb +106 -0
  15. data/example/sudoku.rb +56 -0
  16. data/lib/gecode.dll +0 -0
  17. data/lib/gecoder.rb +5 -0
  18. data/lib/gecoder/bindings.rb +96 -0
  19. data/lib/gecoder/bindings/bindings.rb +2029 -0
  20. data/lib/gecoder/interface.rb +9 -0
  21. data/lib/gecoder/interface/binding_changes.rb +9 -0
  22. data/lib/gecoder/interface/branch.rb +163 -0
  23. data/lib/gecoder/interface/constraints.rb +471 -0
  24. data/lib/gecoder/interface/constraints/bool/boolean.rb +251 -0
  25. data/lib/gecoder/interface/constraints/bool/channel.rb +7 -0
  26. data/lib/gecoder/interface/constraints/bool/linear.rb +200 -0
  27. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +68 -0
  28. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +106 -0
  29. data/lib/gecoder/interface/constraints/bool_enum/relation.rb +55 -0
  30. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +84 -0
  31. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +155 -0
  32. data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
  33. data/lib/gecoder/interface/constraints/fixnum_enum/element.rb +63 -0
  34. data/lib/gecoder/interface/constraints/fixnum_enum/operation.rb +65 -0
  35. data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +42 -0
  36. data/lib/gecoder/interface/constraints/int/arithmetic.rb +150 -0
  37. data/lib/gecoder/interface/constraints/int/channel.rb +51 -0
  38. data/lib/gecoder/interface/constraints/int/domain.rb +80 -0
  39. data/lib/gecoder/interface/constraints/int/linear.rb +143 -0
  40. data/lib/gecoder/interface/constraints/int/relation.rb +141 -0
  41. data/lib/gecoder/interface/constraints/int_enum/arithmetic.rb +63 -0
  42. data/lib/gecoder/interface/constraints/int_enum/channel.rb +86 -0
  43. data/lib/gecoder/interface/constraints/int_enum/count.rb +66 -0
  44. data/lib/gecoder/interface/constraints/int_enum/distinct.rb +64 -0
  45. data/lib/gecoder/interface/constraints/int_enum/element.rb +64 -0
  46. data/lib/gecoder/interface/constraints/int_enum/equality.rb +37 -0
  47. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +187 -0
  48. data/lib/gecoder/interface/constraints/int_enum/sort.rb +135 -0
  49. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +95 -0
  50. data/lib/gecoder/interface/constraints/int_var_constraints.rb +230 -0
  51. data/lib/gecoder/interface/constraints/reifiable_constraints.rb +78 -0
  52. data/lib/gecoder/interface/constraints/selected_set/select.rb +120 -0
  53. data/lib/gecoder/interface/constraints/selected_set_constraints.rb +75 -0
  54. data/lib/gecoder/interface/constraints/set/cardinality.rb +65 -0
  55. data/lib/gecoder/interface/constraints/set/channel.rb +51 -0
  56. data/lib/gecoder/interface/constraints/set/connection.rb +130 -0
  57. data/lib/gecoder/interface/constraints/set/domain.rb +156 -0
  58. data/lib/gecoder/interface/constraints/set/include.rb +36 -0
  59. data/lib/gecoder/interface/constraints/set/operation.rb +118 -0
  60. data/lib/gecoder/interface/constraints/set/relation.rb +155 -0
  61. data/lib/gecoder/interface/constraints/set_elements/relation.rb +116 -0
  62. data/lib/gecoder/interface/constraints/set_elements_constraints.rb +97 -0
  63. data/lib/gecoder/interface/constraints/set_enum/channel.rb +45 -0
  64. data/lib/gecoder/interface/constraints/set_enum/distinct.rb +43 -0
  65. data/lib/gecoder/interface/constraints/set_enum/operation.rb +69 -0
  66. data/lib/gecoder/interface/constraints/set_enum/select.rb +79 -0
  67. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +84 -0
  68. data/lib/gecoder/interface/constraints/set_var_constraints.rb +243 -0
  69. data/lib/gecoder/interface/enum_matrix.rb +64 -0
  70. data/lib/gecoder/interface/enum_wrapper.rb +205 -0
  71. data/lib/gecoder/interface/model.rb +453 -0
  72. data/lib/gecoder/interface/model_sugar.rb +84 -0
  73. data/lib/gecoder/interface/search.rb +197 -0
  74. data/lib/gecoder/interface/variables.rb +306 -0
  75. data/lib/gecoder/version.rb +4 -0
  76. data/specs/bool_var.rb +81 -0
  77. data/specs/branch.rb +185 -0
  78. data/specs/constraints/bool/boolean.rb +317 -0
  79. data/specs/constraints/bool/boolean_properties.rb +51 -0
  80. data/specs/constraints/bool/linear.rb +213 -0
  81. data/specs/constraints/bool_enum/bool_enum_relation.rb +117 -0
  82. data/specs/constraints/bool_enum/channel.rb +102 -0
  83. data/specs/constraints/bool_enum/extensional.rb +225 -0
  84. data/specs/constraints/constraint_helper.rb +234 -0
  85. data/specs/constraints/constraint_receivers.rb +103 -0
  86. data/specs/constraints/constraints.rb +26 -0
  87. data/specs/constraints/fixnum_enum/element.rb +58 -0
  88. data/specs/constraints/fixnum_enum/operation.rb +67 -0
  89. data/specs/constraints/int/arithmetic.rb +149 -0
  90. data/specs/constraints/int/channel.rb +101 -0
  91. data/specs/constraints/int/domain.rb +106 -0
  92. data/specs/constraints/int/linear.rb +183 -0
  93. data/specs/constraints/int/linear_properties.rb +97 -0
  94. data/specs/constraints/int/relation.rb +84 -0
  95. data/specs/constraints/int_enum/arithmetic.rb +72 -0
  96. data/specs/constraints/int_enum/channel.rb +57 -0
  97. data/specs/constraints/int_enum/count.rb +72 -0
  98. data/specs/constraints/int_enum/distinct.rb +80 -0
  99. data/specs/constraints/int_enum/element.rb +61 -0
  100. data/specs/constraints/int_enum/equality.rb +29 -0
  101. data/specs/constraints/int_enum/extensional.rb +224 -0
  102. data/specs/constraints/int_enum/sort.rb +167 -0
  103. data/specs/constraints/operands.rb +264 -0
  104. data/specs/constraints/property_helper.rb +443 -0
  105. data/specs/constraints/reification_sugar.rb +69 -0
  106. data/specs/constraints/selected_set/select.rb +56 -0
  107. data/specs/constraints/selected_set/select_properties.rb +157 -0
  108. data/specs/constraints/set/cardinality.rb +58 -0
  109. data/specs/constraints/set/cardinality_properties.rb +46 -0
  110. data/specs/constraints/set/channel.rb +77 -0
  111. data/specs/constraints/set/connection.rb +176 -0
  112. data/specs/constraints/set/domain.rb +197 -0
  113. data/specs/constraints/set/include.rb +36 -0
  114. data/specs/constraints/set/operation.rb +132 -0
  115. data/specs/constraints/set/relation.rb +117 -0
  116. data/specs/constraints/set_elements/relation.rb +84 -0
  117. data/specs/constraints/set_enum/channel.rb +80 -0
  118. data/specs/constraints/set_enum/distinct.rb +59 -0
  119. data/specs/constraints/set_enum/operation.rb +111 -0
  120. data/specs/constraints/set_enum/select.rb +73 -0
  121. data/specs/distribution.rb +14 -0
  122. data/specs/enum_matrix.rb +43 -0
  123. data/specs/enum_wrapper.rb +179 -0
  124. data/specs/examples.rb +17 -0
  125. data/specs/int_var.rb +163 -0
  126. data/specs/logging.rb +24 -0
  127. data/specs/model.rb +325 -0
  128. data/specs/model_sugar.rb +30 -0
  129. data/specs/search.rb +383 -0
  130. data/specs/selected_set.rb +39 -0
  131. data/specs/set_elements.rb +34 -0
  132. data/specs/set_var.rb +82 -0
  133. data/specs/spec_helper.rb +265 -0
  134. data/tasks/all_tasks.rb +1 -0
  135. data/tasks/dependencies.txt +22 -0
  136. data/tasks/distribution.rake +194 -0
  137. data/tasks/rcov.rake +18 -0
  138. data/tasks/specs.rake +21 -0
  139. data/tasks/svn.rake +16 -0
  140. data/tasks/website.rake +51 -0
  141. data/vendor/gecode/win32/lib/libgecodeint.dll +0 -0
  142. data/vendor/gecode/win32/lib/libgecodekernel.dll +0 -0
  143. data/vendor/gecode/win32/lib/libgecodeminimodel.dll +0 -0
  144. data/vendor/gecode/win32/lib/libgecodesearch.dll +0 -0
  145. data/vendor/gecode/win32/lib/libgecodeset.dll +0 -0
  146. data/vendor/gecode/win32/lib/libgecodesupport.dll +0 -0
  147. data/vendor/rust/README +28 -0
  148. data/vendor/rust/bin/cxxgenerator.rb +93 -0
  149. data/vendor/rust/include/rust_checks.hh +116 -0
  150. data/vendor/rust/include/rust_conversions.hh +102 -0
  151. data/vendor/rust/rust.rb +67 -0
  152. data/vendor/rust/rust/attribute.rb +51 -0
  153. data/vendor/rust/rust/bindings.rb +172 -0
  154. data/vendor/rust/rust/class.rb +337 -0
  155. data/vendor/rust/rust/constants.rb +48 -0
  156. data/vendor/rust/rust/container.rb +110 -0
  157. data/vendor/rust/rust/cppifaceparser.rb +129 -0
  158. data/vendor/rust/rust/cwrapper.rb +72 -0
  159. data/vendor/rust/rust/cxxclass.rb +96 -0
  160. data/vendor/rust/rust/element.rb +81 -0
  161. data/vendor/rust/rust/enum.rb +63 -0
  162. data/vendor/rust/rust/function.rb +407 -0
  163. data/vendor/rust/rust/namespace.rb +61 -0
  164. data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
  165. data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
  166. data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
  167. data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
  168. data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
  169. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
  170. data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
  171. data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
  172. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +100 -0
  173. data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
  174. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +26 -0
  175. data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
  176. data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
  177. data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
  178. data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
  179. data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
  180. data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
  181. data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
  182. data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
  183. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +7 -0
  184. data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
  185. data/vendor/rust/rust/type.rb +98 -0
  186. data/vendor/rust/test/Makefile +4 -0
  187. data/vendor/rust/test/constants.rb +36 -0
  188. data/vendor/rust/test/cppclass.cc +45 -0
  189. data/vendor/rust/test/cppclass.hh +67 -0
  190. data/vendor/rust/test/cppclass.rb +59 -0
  191. data/vendor/rust/test/cwrapper.c +74 -0
  192. data/vendor/rust/test/cwrapper.h +41 -0
  193. data/vendor/rust/test/cwrapper.rb +56 -0
  194. data/vendor/rust/test/dummyclass.hh +31 -0
  195. data/vendor/rust/test/lib/extension-test.rb +98 -0
  196. data/vendor/rust/test/operators.cc +41 -0
  197. data/vendor/rust/test/operators.hh +39 -0
  198. data/vendor/rust/test/operators.rb +39 -0
  199. data/vendor/rust/test/test-constants.rb +43 -0
  200. data/vendor/rust/test/test-cppclass.rb +82 -0
  201. data/vendor/rust/test/test-cwrapper.rb +80 -0
  202. data/vendor/rust/test/test-operators.rb +42 -0
  203. metadata +393 -0
data/README ADDED
@@ -0,0 +1,58 @@
1
+ = Gecode/R
2
+
3
+ Website: http://gecoder.org
4
+
5
+ Gecode/R is a Ruby interface to the Gecode constraint programming library.
6
+ Gecode/R is intended for people with no previous experience of constraint
7
+ programming, aiming to be easy to pick up and use.
8
+
9
+ See Gecode::Model to get started.
10
+
11
+ == Warning
12
+
13
+ Gecode/R is still in a development stage, the syntax is by no means final
14
+ and backwards compatibility will be broken time and time again. Don't use
15
+ Gecode/R in production-code yet, it's merely available at this point to allow
16
+ people to play with it and give feedback.
17
+
18
+ == Installation
19
+
20
+ Gecode/R requires Gecode 2.1.1, which can be downloaded from
21
+ http://www.gecode.org/download.html . See
22
+ http://www.gecode.org/gecode-doc-latest/PageComp.html for the installation
23
+ instructions.
24
+
25
+ === Installing from gem
26
+
27
+ There are two gems. The first includes only Gecode/R, and assumes that you have
28
+ installed Gecode yourself. The second includes both Gecode/R and Gecode. If you
29
+ use Windows then you're recommended to use the second one, even though you
30
+ already have Gecode, as the other one does not come in a pre-compiled variant.
31
+
32
+ Gecode/R only:
33
+ gem install gecoder
34
+
35
+ Gecode/R and Gecode:
36
+ gem install gecoder-with-gecode
37
+
38
+ === Installing from source using gem
39
+
40
+ rake gem
41
+ gem install pkg/gecoder-0.x.x.gem
42
+
43
+ === Installing from source without using gem
44
+
45
+ "gecode.so" might have another extension depending on which platform it's
46
+ generated on (replace the extension in the following commands with whatever
47
+ extension it's given).
48
+
49
+ cd ext
50
+ ruby extconf.rb
51
+ make
52
+ mv gecode.so ../lib/
53
+
54
+ === Running the tests
55
+
56
+ rake specs
57
+
58
+ Requires RSpec (1.0.5, but other version should hopefully work).
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/gempackagetask'
5
+
6
+ require 'tasks/all_tasks'
7
+ task :default => [:verify_rcov, :example_specs]
8
+
9
+ desc 'Performs the tasks necessary when releasing'
10
+ task :release => [:clobber, :verify_rcov, :example_specs, :publish_website,
11
+ :publish_packages, :tag]
12
+
13
+ desc 'Runs all the tests'
14
+ task :test => :specs
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/example_helper'
2
+
3
+ class EquationProblem < Gecode::Model
4
+ def initialize
5
+ x, y, z = vars_is_an int_var_array(3, 0..9)
6
+
7
+ (x + y).must == z
8
+ x.must == y - 3
9
+
10
+ branch_on vars
11
+ end
12
+ end
13
+
14
+ puts 'x y z'
15
+ puts EquationProblem.new.solve!.vars.values.join(' ')
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + '/../lib/gecoder'
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/example_helper'
2
+
3
+ # Solves the magic sequence problem.
4
+ class MagicSequence < Gecode::Model
5
+ # n is the length of the sequence.
6
+ def initialize(n)
7
+ # The i:th variable represents the value of the i:th element in the
8
+ # sequence.
9
+ sequence_is_an int_var_array(n, 0...n)
10
+
11
+ # The basic requirement to qualify as a magic sequence.
12
+ n.times{ |i| sequence.count(i).must == sequence[i] }
13
+
14
+ # The following are implied constraints. They do not affect which
15
+ # assignments are solutions, but they do help prune the search space
16
+ # quicker.
17
+
18
+ # The sum must be n. This follows from that there are exactly n elements and
19
+ # that the sum of all elements are the number of occurrences in total, i.e.
20
+ # the number of elements.
21
+ sequence.sum.must == n
22
+
23
+ # sum(seq[i] * (i-1)) must equal 0 because sum(seq[i]) = n as seen above
24
+ # and sum(i*seq[i]) is just another way to compute sum(seq[i]). So we get
25
+ # sum(seq[i] * (i-1)) = sum(seq[i]) - sum(i*seq[i]) = n - n = 0
26
+ sequence.zip((-1...n).to_a).map{ |element, c| element*c }.sum.must == 0
27
+
28
+ branch_on sequence, :variable => :smallest_degree, :value => :split_max
29
+ end
30
+
31
+ def to_s
32
+ sequence.values.join(', ')
33
+ end
34
+ end
35
+
36
+ class Array
37
+ # Sums all the elements in the array using #+ .
38
+ def sum
39
+ inject{ |sum, element| sum + element }
40
+ end
41
+ end
42
+
43
+ puts MagicSequence.new(500).solve!.to_s
data/example/money.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'gecoder'
3
+
4
+ solution = Gecode.solve do
5
+ # A helper to make the linear equation a bit tidier. Takes a number of
6
+ # variables and computes the linear combination as if the variable
7
+ # were digits in a base 10 number. E.g. x,y,z becomes
8
+ # 100*x + 10*y + z .
9
+ def equation_row(*variables)
10
+ variables.inject{ |result, variable| variable + result*10 }
11
+ end
12
+
13
+ # Set up the variables.
14
+ # Let "letters" be an array of 8 integer variables with domain 0..9.
15
+ # The elements represents the letters s, e, n, d, m, o, r and y.
16
+ letters_is_an int_var_array(8, 0..9)
17
+ s,e,n,d,m,o,r,y = letters
18
+
19
+ # Set up the constraints.
20
+ # The equation must hold.
21
+ (equation_row(s, e, n, d) + equation_row(m, o, r, e)).must ==
22
+ equation_row(m, o, n, e, y)
23
+
24
+ # The initial letters may not be 0.
25
+ s.must_not == 0
26
+ m.must_not == 0
27
+
28
+ # All letters must be assigned different digits.
29
+ letters.must_be.distinct
30
+
31
+ # Tell Gecode what variables we want to know the values of.
32
+ branch_on letters, :variable => :smallest_size, :value => :min
33
+ end
34
+
35
+ puts 's e n d m o r y'
36
+ puts solution.letters.values.join(' ')
data/example/queens.rb ADDED
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/example_helper'
2
+
3
+ # Solves the n-queens problem: http://en.wikipedia.org/wiki/Nqueens . No attempt
4
+ # to break the involved symmetries is made.
5
+ class NQueens < Gecode::Model
6
+ def initialize(n)
7
+ @size = n
8
+
9
+ # The row number that the queen in the i:th column has. By using this as
10
+ # our variables we already make sure that no two queens are in the same
11
+ # column.
12
+ queen_rows_is_an int_var_array(n, 0...n)
13
+
14
+ # Set up the constraints
15
+ # Queens must not be in the same diagonal (negative slope).
16
+ queen_rows.must_be.distinct(:offsets => (0...n).to_a)
17
+ # Queens must not be in the same diagonal (positive slope).
18
+ queen_rows.must_be.distinct(:offsets => (0...n).to_a.reverse)
19
+ # Queens must not be in the same row.
20
+ queen_rows.must_be.distinct
21
+
22
+ # Branching, we use first-fail heuristic.
23
+ branch_on queen_rows, :variable => :smallest_size, :value => :min
24
+ end
25
+
26
+ # Displays the assignment as a chessboard with queens denoted by 'x'.
27
+ def to_s
28
+ rows = queen_rows.values
29
+
30
+ separator = '+' << '-' * (3 * @size + (@size - 1)) << "+\n"
31
+ res = (0...@size).inject(separator) do |s, i|
32
+ (0...@size).inject(s + '|') do |s, j|
33
+ s << " #{rows[j] == i ? 'x' : ' '} |"
34
+ end << "\n" << separator
35
+ end
36
+ end
37
+ end
38
+
39
+ # Print the first solution. Note that there are 92 solutions, but only 12
40
+ # are rotationally distinct. For any serious use one should place additional
41
+ # constraints to eliminate those symmetries.
42
+ puts NQueens.new((ARGV[0] || 8).to_i).solve!.to_s
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/example_helper'
2
+
3
+ # Solves the send+more=money problem:
4
+ # http://en.wikipedia.org/wiki/Send%2Bmore%3Dmoney
5
+ class SendMoreMoney < Gecode::Model
6
+ def initialize
7
+ # Set up the variables, 8 letters with domain 0..9.
8
+ s,e,n,d,m,o,r,y = @letters = int_var_array(8, 0..9)
9
+
10
+ # Set up the constraints.
11
+ # The equation must hold.
12
+ (equation_row(s, e, n, d) + equation_row(m, o, r, e)).must ==
13
+ equation_row(m, o, n, e, y)
14
+
15
+ # The initial letters may not be 0.
16
+ s.must_not == 0
17
+ m.must_not == 0
18
+
19
+ # All letters must be assigned different digits.
20
+ @letters.must_be.distinct
21
+
22
+ # Set the branching.
23
+ branch_on @letters, :variable => :smallest_size, :value => :min
24
+ end
25
+
26
+ def to_s
27
+ %w{s e n d m o r y}.zip(@letters).map do |text, letter|
28
+ "#{text}: #{letter.value}"
29
+ end.join(', ')
30
+ end
31
+
32
+ private
33
+
34
+ # A helper to make the linear equation a bit tidier. Takes a number of
35
+ # variables and computes the linear combination as if the variable
36
+ # were digits in a base 10 number. E.g. x,y,z becomes
37
+ # 100*x + 10*y + z .
38
+ def equation_row(*variables)
39
+ variables.inject{ |result, variable| variable + result*10 }
40
+ end
41
+ end
42
+
43
+ puts SendMoreMoney.new.solve!.to_s
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/example_helper'
2
+
3
+ # Solves the cryptarithmetic send+most=money problem while maximizing the value
4
+ # of "money".
5
+ class SendMoreMoney < Gecode::Model
6
+ attr :money
7
+
8
+ def initialize
9
+ # Set up the variables, 9 letters with domain 0..9.
10
+ s,e,n,d,m,o,s,t,y = @letters = int_var_array(9, 0..9)
11
+ @money = wrap_enum([m,o,n,e,y])
12
+
13
+ # Set up the constraints.
14
+ # The equation must hold.
15
+ (equation_row(s, e, n, d) + equation_row(m, o, s, t)).must ==
16
+ equation_row(m,o,n,e,y)
17
+
18
+ # The initial letters may not be 0.
19
+ s.must_not == 0
20
+ m.must_not == 0
21
+
22
+ # All letters must be assigned different digits.
23
+ @letters.must_be.distinct
24
+
25
+ # Set the branching.
26
+ branch_on @letters, :variable => :smallest_size, :value => :min
27
+ end
28
+
29
+ def to_s
30
+ %w{s e n d m o s t y}.zip(@letters).map do |text, letter|
31
+ "#{text}: #{letter.value}"
32
+ end.join(', ')
33
+ end
34
+
35
+ private
36
+
37
+ # A helper to make the linear equation a bit tidier. Takes a number of
38
+ # variables and computes the linear combination as if the variable
39
+ # were digits in a base 10 number. E.g. x,y,z becomes
40
+ # 100*x + 10*y + z .
41
+ def equation_row(*variables)
42
+ variables.to_number
43
+ end
44
+ end
45
+
46
+ class Array
47
+ # Computes a number of the specified base using the array's elements as
48
+ # digits.
49
+ def to_number(base = 10)
50
+ inject{ |result, variable| variable + result * base }
51
+ end
52
+ end
53
+
54
+ solution = SendMoreMoney.new.optimize! do |model, best_so_far|
55
+ model.money.to_number.must > best_so_far.money.values.to_number
56
+ end
57
+ puts solution.to_s
58
+ puts "money: #{solution.money.values.to_number}"
@@ -0,0 +1,84 @@
1
+ require File.dirname(__FILE__) + '/example_helper'
2
+
3
+ # Solves the square tiling problem. The objective is to pack supplied squares
4
+ # into a bigger rectangle so that there is no overlap.
5
+ class SquareTiling < Gecode::Model
6
+ # Takes the width and height of the rectangle to pack the squares into. Then
7
+ # the sizes of the squares that should be packed into the rectangle. The sizes
8
+ # must be sorted.
9
+ def initialize(width, height, square_sizes)
10
+ @sizes = square_sizes
11
+ @square_count = @sizes.size
12
+
13
+ # The coordinates of the placed squares.
14
+ @xs = int_var_array(@square_count, 0..(width - @sizes.min))
15
+ @ys = int_var_array(@square_count, 0..(height - @sizes.min))
16
+
17
+ # The essential constraints of the problem.
18
+ @square_count.times do |i|
19
+ # Each square must be placed within the bounds
20
+ @xs[i].must <= width - @sizes[i]
21
+ @ys[i].must <= height - @sizes[i]
22
+
23
+ # Pairwise conditions, no pair of squares may overlap.
24
+ 0.upto(i - 1) do |j|
25
+ # That the two squares don't overlap means that i is left of j,
26
+ # or j is left of i, or i is above j, or j is above i.
27
+ ((@xs[j] - @xs[i]).must >= @sizes[i]) |
28
+ ((@xs[i] - @xs[j]).must >= @sizes[j]) |
29
+ ((@ys[j] - @ys[i]).must >= @sizes[i]) |
30
+ ((@ys[i] - @ys[j]).must >= @sizes[j])
31
+ end
32
+ end
33
+
34
+ # A couple of implied constraints that only serve to make the solving
35
+ # faster:
36
+
37
+ # The combined size of all squares occupying a column must be equal to the
38
+ # total height.
39
+ occupied_length_must_equal_total_length(height, width, @xs)
40
+ # The combined size of all squares occupying a row must be equal to the
41
+ # total width.
42
+ occupied_length_must_equal_total_length(width, height, @ys)
43
+
44
+ # Symmetry-breaking constraint: Order squares of the same size.
45
+ @square_count.times do |i|
46
+ @xs[i].must <= @xs[i+1] if @sizes[i] == @sizes[i+1]
47
+ end
48
+
49
+ # Place the squares left to right on the x-axis first, then the y-axis.
50
+ branch_on @xs, :variable => :smallest_min, :value => :min
51
+ branch_on @ys, :variable => :smallest_min, :value => :min
52
+ end
53
+
54
+ # Constrains the combined length of the squares in the same row or column to
55
+ # equal +total_length+ in the axis of the specified coordinates +coords+,
56
+ # which is +axist_length+ long.
57
+ def occupied_length_must_equal_total_length(total_length, axis_length, coords)
58
+ axis_length.times do |i|
59
+ # We create an array of boolean variables and constrain it so that element
60
+ # +j+ is true iff square +j+ occupies +i+ (+i+ being a row or column).
61
+ occupied = bool_var_array(@square_count)
62
+ occupied.each_with_index do |is_occupying, j|
63
+ coords[j].must_be.in((i - @sizes[j] + 1)..i, :reify => is_occupying)
64
+ end
65
+
66
+ # Constrain the combined length of squares that are occupying +i+ to equal
67
+ # the total length. We multiply the sizes with the boolean variables
68
+ # since a boolean in linear equation is 0 if assigned false and 1 if
69
+ # assigned true. Hence we will mask out the sizes of any squares not in
70
+ # +i+.
71
+ occupied_sizes = occupied.zip(@sizes).map{ |bool, size| bool*size }
72
+ occupied_sizes.inject(0){ |sum, x| x + sum }.must.equal(total_length,
73
+ :strength => :domain)
74
+ end
75
+ end
76
+
77
+ # Displays the coordinates of the squares.
78
+ # TODO: Something more impressive.
79
+ def to_s
80
+ @xs.values.zip(@ys.values).map{ |x,y| "(#{x}, #{y})"}.join(', ')
81
+ end
82
+ end
83
+
84
+ puts SquareTiling.new(65, 47, [25, 24, 23, 22, 19, 17, 11, 6, 5, 3]).solve!.to_s
@@ -0,0 +1,106 @@
1
+ require File.dirname(__FILE__) + '/example_helper'
2
+ require 'enumerator'
3
+
4
+ # Solves the sudoku problem using sets. The model used is a fairly direct
5
+ # translation of the corresponding Gecode example:
6
+ # http://www.gecode.org/gecode-doc-latest/sudoku-set_8cc-source.html .
7
+ class SudokuSet < Gecode::Model
8
+ # Takes a 9x9 matrix of values in the initial sudoku, 0 if the square is
9
+ # empty.
10
+ def initialize(predefined_values)
11
+ # Verify that the input is of a valid size.
12
+ @size = n = predefined_values.row_size
13
+ block_size = Math.sqrt(n).round
14
+ unless predefined_values.square? and block_size**2 == n
15
+ raise ArgumentError, 'Incorrect value matrix size.'
16
+ end
17
+ sub_count = block_size
18
+
19
+ # Create one set per assignable number (i.e. 1..9). Each set contains the
20
+ # position of all squares that the number is located in. The squares are
21
+ # given numbers from 1 to 81. Each set therefore has an empty lower bound
22
+ # (since we have no guarantees where a number will end up) and 1..81 as
23
+ # upper bound (as it may potentially occurr in any square). We know that
24
+ # each assignable number must occurr 9 times in a solved sudoku, so we
25
+ # set the cardinality to 9..9 .
26
+ sets_is_an set_var_array(n, [], 1..n*n, n..n)
27
+ predefined_values.row_size.times do |i|
28
+ predefined_values.column_size.times do |j|
29
+ unless predefined_values[i,j].zero?
30
+ # We add the constraint that the square position must occurr in the
31
+ # set corresponding to the predefined value.
32
+ sets[predefined_values[i,j] - 1].must_be.superset_of [i*n + j+1]
33
+ end
34
+ end
35
+ end
36
+
37
+ # Build arrays containing the square positions of each row and column.
38
+ rows = []
39
+ columns = []
40
+ n.times do |i|
41
+ rows << ((i*n + 1)..(i*n + n))
42
+ columns << (0...n).map{ |e| e*n + 1 + i }
43
+ end
44
+
45
+ # Build arrays containing the square positions of each block.
46
+ blocks = []
47
+ # The square numbers of the first block.
48
+ first_block = (0...block_size).map do |e|
49
+ ((n*e+1)..(n*e+block_size)).to_a
50
+ end.flatten
51
+ block_size.times do |i|
52
+ block_size.times do |j|
53
+ blocks << first_block.map{ |e| e + (j*n*block_size)+(i*block_size) }
54
+ end
55
+ end
56
+
57
+ # All sets must be pairwise disjoint since two numbers can't be assigned to
58
+ # the same square.
59
+ n.times do |i|
60
+ (i + 1).upto(n - 1) do |j|
61
+ sets[i].must_be.disjoint_with sets[j]
62
+ end
63
+ end
64
+
65
+ # The sets must intersect in exactly one element with each row column and
66
+ # block. I.e. an assignable number must be assigned exactly once in each
67
+ # row, column and block.
68
+ sets.each do |set|
69
+ rows.each do |row|
70
+ set.intersection(row).size.must == 1
71
+ end
72
+ columns.each do |column|
73
+ set.intersection(column).size.must == 1
74
+ end
75
+ blocks.each do |block|
76
+ set.intersection(block).size.must == 1
77
+ end
78
+ end
79
+
80
+ # Branching.
81
+ branch_on sets, :variable => :none, :value => :min
82
+ end
83
+
84
+ # Outputs the assigned numbers in a grid.
85
+ def to_s
86
+ squares = []
87
+ sets.values.each_with_index do |positions, i|
88
+ positions.each{ |square_position| squares[square_position - 1] = i + 1 }
89
+ end
90
+ squares.enum_slice(@size).map{ |slice| slice.join(' ') }.join("\n")
91
+ end
92
+ end
93
+
94
+ predefined_squares = Matrix[
95
+ [0,0,0, 2,0,5, 0,0,0],
96
+ [0,9,0, 0,0,0, 7,3,0],
97
+ [0,0,2, 0,0,9, 0,6,0],
98
+
99
+ [2,0,0, 0,0,0, 4,0,9],
100
+ [0,0,0, 0,7,0, 0,0,0],
101
+ [6,0,9, 0,0,0, 0,0,1],
102
+
103
+ [0,8,0, 4,0,0, 1,0,0],
104
+ [0,6,3, 0,0,0, 0,8,0],
105
+ [0,0,0, 6,0,8, 0,0,0]]
106
+ puts SudokuSet.new(predefined_squares).solve!.to_s