Genetic Madlibs

Posted by Jeremy Voorhis Fri, 06 Apr 2007 20:47:00 GMT

Inspired by the eigenclass language generator, I’ve thrown together an example of how it would be implemented with the Directed Ruby Programming library. Directed programming is an interesting hybrid of genetic programming and the recently discovered grammatical evolution technique which generates a program tree according to a grammar.

This example may not be very interesting for those familiar with evolutionary programming techniques, but it created a fun diversion, highlights how the DRP library is to be used, and shows a different solution for a language generator.


class DrpGenerator
  extend DRP::RuleEngine
  begin_rules
    def main() "#{hello}\n#{ex1}\n#{ex2}" end

    def hello() "Hello, #{somebody}!" end

    def somebody() "matz" end
    def somebody() "world" end

    def ex1() "This is a more #{adj1} #{example}." end

    def adj1() "complex" end
    def adj1() "elaborate" end

    def example() "example" end
    def example() "test" end

    def ex2() "Some simple sentence." end
    def ex2() "Another, involving harder stuff." end
    def ex2() "Another, involving a more complex #{exp}." end
    def ex2() "Yet another possibility; each one is chosen with an evolutionary algorithm." end

    def exp() "expression" end
    def exp() "disjunction" end
    def exp() example end
  end_rules
end

g = DrpGenerator.new
3.times { puts g.main }

Hello, matz!
This is a more elaborate example.
Another, involving a more complex disjunction.

Hello, world!
This is a more elaborate test.
Another, involving harder stuff.

Hello, world!
This is a more complex example.
Yet another possibility; each one is chosen with an evolutionary algorithm.

My DrpGenerator isn’t as readable or attractive as the eigenclass DSL, and multiple definitions of the same method will likely confuse most Rubyists at first glance, but makes it easy to see the underlying grammar.

Comments

  1. RSL said about 16 hours later:

    Since you mention it… What does the multiple method definitions do? Besides confuse most of us. ;) I would have thought that only the last definition would be “available” but your examples show that’s not the case.

  2. JV said 2 days later:

    Good question. DRP uses the exotic and undocumented Module#method_added callback to alias the method with a unique name and change its access to private. This behavior takes effect between the begin_rules and end_rules invocations. When end_rules is called, methods are defined that forward the call to DRP’s dispatching system, which in turn dispatches to one of the original methods.

    Here is a closer look at what’s going on in my DrpGenerator class.

    
    irb(main):038:0> gen.private_methods.grep(/drp/)
    => ["__drp__somebody__1", "__drp__example__1", "__drp__exp__0",
    "__drp__ex1__0", "__drp__ex2__0", "__drp__main__0",
    "__drp__exp__1", "__drp__call__method", "__drp__adj1__0",
    "__drp__ex2__1", "__drp__hello__0", "__drp__exp__2",
    "__drp__adj1__1", "__drp__ex2__2", "__drp__somebody__0",
    "__drp__example__0", "__drp__choose__method", "__drp__ex2__3"]
    
  3. JV said 2 days later:

    Take a peek at Module#method_added for a good look at how this works.

(leave url/email »)