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

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