Gecode/r
Recently I solved my first constraint programming problem using C# (Steve Eichert also solved it via Ruby). I decided to poke around the Internet to see if there's an API for constraint programming. After all, there are real world problems that can be solved using constraint programming. I can't imagine people just hand roll there own API for complex problems.
After few searches in google, I came across Gecode. Gecode is an open source API implemented in C++ distributed under the BSD style license. I noticed there is also Gecode/J which is a Java interface to Gecode. I started to wonder, is there a Ruby version of Gecode? It turns out Andreas Launila recently started Gecode/r under Google Summer of Code.
Gecode/r is still at the early stage, but there is a downloadable alpha version. I tried to use it to solve the same problem, however, I ran into some difficulties. It currently only supports 3 mathematical operations: +, -, *. No division for now. Andreas suggested I rewrite the equation by removing the division. The only problem with rewriting is that the equation actually becomes more complex. I haven't been able to get my version to work yet.
For those who are interested in what Gecode/r looks like, below is an example of solving the classic send more money problem using gecode/r, which is taken from gecode/r's example page:
class SendMoreMoney < Gecode::Model
def initialize
s,e,n,d,m,o,r,y = @letters = int_var_array(8, 0..9)
(equation_row(s, e, n, d) + equation_row(m, o, r, e)).must ==
equation_row(m, o, n, e, y)
s.must_not == 0
m.must_not == 0
@letters.must_be.distinct
branch_on @letters, :variable => :smallest_size, :value => :min
end
def to_s
%w{s e n d m o r y}.zip(@letters).map do |text, letter|
"#{text}: #{letter.val}"
end.join(', ')
end
private
# A helper to make the linear equation a bit tidier. Takes a number of
# variables and computes the linear combination as if the variable
# were digits in a base 10 number. E.g. x,y,z becomes
# 100*x + 10*y + z .
def equation_row(*variables)
variables.inject{ |result, variable| variable + result*10 }
end
end
puts SendMoreMoney.new.solve!.to_s