Gecode/r

Posted by Aaron Feng Fri, 06 Jul 2007 01:10:00 GMT

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
Comments

Leave a response

Comments