<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Johannes Thönes &#187; Thesis</title>
	<atom:link href="http://blog.jthoenes.net/category/diplomarbeit/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jthoenes.net</link>
	<description>Thoughts, Remarks and Tutorials from my Life and my Works.</description>
	<lastBuildDate>Sat, 07 Jan 2012 15:34:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Speeding up iterative calculation in Ruby</title>
		<link>http://blog.jthoenes.net/2009/02/27/speeding-up-iterative-calculation-in-ruby/</link>
		<comments>http://blog.jthoenes.net/2009/02/27/speeding-up-iterative-calculation-in-ruby/#comments</comments>
		<pubDate>Fri, 27 Feb 2009 17:45:18 +0000</pubDate>
		<dc:creator>Johannes Thönes</dc:creator>
				<category><![CDATA[Thesis]]></category>
		<category><![CDATA[Klinische Studien]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://jthoenes.bergischweb.de/?p=64</guid>
		<description><![CDATA[The domain background of my diploma thesis is sample size calculation for clinical trials &#8211; in fact simulation of those. This means I need to calculate how many probands or trial subjects are needed, to get the result with a certain error propability (I don&#8217;t mind going into detail right here). The procedures for sample [...]]]></description>
			<content:encoded><![CDATA[<p>The domain background of my diploma thesis is sample size calculation for clinical trials &#8211; in fact simulation of those. This means I need to calculate how many probands or trial subjects are needed, to get the result with a certain error propability (I don&#8217;t mind going into detail right here).</p>
<p>The procedures for sample size calculation are well published, but some of those work in a manner like this:</p>
<pre class="brush: ruby; title: ; notranslate">def calculate_sample_size
  n = 4 # 4 is a good starting point
          # a we have 2 arms minimum and a trial with propability involved need 2 probands at least
  loop do
    return n if fullfills_a_some_mathematical_condition(n)
    n += 1
  end
end</pre>
<p>So we need to return the smallest integer fulfilling a certain condition and we need to iterate up to this one, testing against a condition each time.</p>
<p>The above works, but has a big problem: I&#8217;m doing it for at least 10 million times, usually around 100 million times. Caching is not an option here, as we are dealing with stocastic we don&#8217;t have deterministic parameters (those parameters are hidden in the code above).</p>
<p>But, going back to my computer science books, I found &#8216;binary search&#8217; which I applied for this &#8211; of course with a Ruby closure:</p>
<pre class="brush: ruby; title: ; notranslate">module IterationHelper
  # This is the entry point for the iteration
  def iterate_up start = 0, step = 1000, &amp;amp;block
    max = start
    # First we need to find the a maximum, because in theory we have infinite integers
    # I define the step parameters, as for some sample size calculation, there is a way to guess those to
    #   some extend.
    # I could of course start with Fixnum::MAX but I in my case this is faster
    until(yield(max))
      max += step
    end

    # Now that we know the range where to look for the smallest match
    find_smallest_satisfier(max - step, max, &amp;amp;block)
  end

  private
  # This works nearly exactly as textbooks binary sort
  def find_smallest_satisfier min, max, &amp;amp;block

    # If min and max differ less than 2, we have found the smallest n
    if max - min &amp;lt; 2
      return min if yield(min)
      return max
    end

    # Get the value in the middle
    n = min + (max-min)/2
    # If yield(n) ==&amp;gt; value might be smaller
    if yield(n)
      return find_smallest_satisfier(min, n, &amp;amp;block)
      # Unless yield(n) ==&amp;gt; value might be bigger
    else
      return find_smallest_satisfier(n, max, &amp;amp;block)
    end
  end
end</pre>
<p>This leeds to a much cleaner call like this:</p>
<pre class="brush: ruby; title: ; notranslate">include IterationHelper
def sample_size
  iterate_up {|n| fullfills_a_some_mathematical_condition(n) }
 end</pre>
<p>But &#8211; i did say &#8211; I didn&#8217;t do this for cleaner calls. So I did a litte benchmark:</p>
<pre class="brush: ruby; title: ; notranslate">require 'lib/helpers/iteration_helper'
include IterationHelper

require 'benchmark'
include Benchmark

N = 10**3

def complex_calculation n
  # some dummy calculations
  10.times {Math.sqrt Kernel.rand}
  n &amp;gt;= @n_0
end
@targets = [25, 105, 234, 500, 765]

bm(7) do |x|
  x.report(&quot;normal&quot;) do
  @targets.each do |t|
    @n_0 = t
      N.times do
        m = 4
        loop do
           break if complex_calculation(m)
           m += 1
        end
      end
    end
  end

  x.report(&quot;binary&quot;) do
    @targets.each do |t|
        @n_0 = t
        N.times do
        iterate_up(4) {|n| complex_calculation(n)}
      end
    end
  end
end1
The result was very impressing:

1 user     system      total        real
normal  12.210000   0.030000  12.240000 ( 15.631090)
binary   0.520000   0.010000   0.530000 (  0.778788)</pre>
<p>You should - of course - expect the iteration do do better, when the actual satisfaction test needs less mathematics, but perform worse if the mathematics are more time consuming (which mine are).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jthoenes.net/2009/02/27/speeding-up-iterative-calculation-in-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Argument Fun with Ruby</title>
		<link>http://blog.jthoenes.net/2009/02/03/argument-fun-with-ruby/</link>
		<comments>http://blog.jthoenes.net/2009/02/03/argument-fun-with-ruby/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 18:02:32 +0000</pubDate>
		<dc:creator>Johannes Thönes</dc:creator>
				<category><![CDATA[Thesis]]></category>
		<category><![CDATA[Klinische Studien]]></category>
		<category><![CDATA[Meta-Programming]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://jthoenes.bergischweb.de/?p=38</guid>
		<description><![CDATA[As some of you might know, my diploma thesis is on simulation with the help of an internal ruby DSL. This DSL will be &#8211; at least I hope so &#8211; full of small little interesting things, making the life of those who use the DSL (i.e. biometricians) easier. This requires some interesting stuff on [...]]]></description>
			<content:encoded><![CDATA[<p>As some of you might know, my diploma thesis is on simulation with the help of an internal ruby DSL. This DSL will be &#8211; at least I hope so &#8211; full of small little interesting things, making the life of those who use the DSL (i.e. <span>biometricians) easier. This requires some interesting stuff on ruby meta programming, that will be posted &#8211; as done -  in this blog. One of them is a thing I call &#8220;multiple parameters&#8221;. So what is it all about?</span></p>
<p><span>First of all we have a method in the DSL:<br />
</span></p>
<pre class="brush: ruby; title: ; notranslate">simulate do
# Some other definition ...
arms do
treatment N([0, 0.1, 0.3], 1)
placebo N(0,1)
end
# Some more definitions ...
end</pre>
<p>The intersting thing happens when you call the N function. If you just call it with simple numeric arguments, you get back a normal distributed sampler. If you call it with an array as one or more arguments, you get back the multiple normal distributed samples &#8211; constructed from the cartesian product of all params. This means, the treatment will get the Array as if you called:</p>
<pre class="brush: ruby; title: ; notranslate">[N(0,1), N(0.1,1), N(0.3,1)]</pre>
<p>The idea behind this is, that if you specify those multiple parameters for the simulation, the simulation is run multiple times &#8211; each time with a sligly different set of definitions.</p>
<p>A direct implementation wouldn&#8217;t be to hard &#8211; at least we are doing ruby. But as this is not only related to the N method, but to a lot of other things as well, I wanted to extract this rather into a model so I could write the N method something like this:</p>
<pre class="brush: ruby; title: ; notranslate">module DistributionHelper
  extend MultipleParameters
  def N mean, variance
    Distribution::Gauss.new(mean,variance)
  end
  mutate_params :N
end</pre>
<p>The MultipleParameters module is implemented following the path, Dave Thomas led in his 5th Episode of &#8220;The Ruby Object Model and Metaprogramming&#8221; for memorization. I&#8217;ll try to explain the module but first have the implementation:</p>
<pre class="brush: ruby; title: ; notranslate">module MultipleParameters
  def mutate_params(name)
    original_method = instance_method(name)

    define_method(name) do |*args|
      mutated_arguments = [[]]
      args.each do |arg|
        if arg.is_a?(Array)
          new_results = []
          mutated_arguments.each do |r|
            arg.each do |a|
              rm = r.clone
              rm &lt; &lt; a
              new_results &lt;&lt; rm
            end
          end
          mutated_arguments = new_results
        else
          mutated_arguments.each { |r| r &amp;lt;&amp;lt; arg  }
        end
      end

      bound_method = original_method.bind(self)
      ret = []
      mutated_arguments.each do |mutated_args|
        ret &lt;&lt; bound_method.call(*mutated_args)
      end

      (ret.size == 1) ? ret.first : ret
    end
  end
end</pre>
<p>So this is a class-level module (i.e. you need to get access to class methods rather than object methods) so you extend your class/module with it rather than including it. After having done this, you can call the mutate_params method for any previously defined method. When called, your originally defined method will get boxed into an object (line 3) and it will be redefinded. The redefined method will create the cartesian product of the argumenes (i.e. ([0,1], [1,2]) yields to (0,1), (0,2), (1,1) and (1,2)) and than create an array of all the results from the calls. Before beeing able to call the originally defined method you have to bind the method to the current self (line 24), because the method will be called as an object method, and than passing all different parameter sets to it.</p>
<p>Finally you have an array of all return values which is returned. The last line is somewhat of convinience as it returns the object directly if you did not specify any multiple parameters.</p>
<p>Note: This approach does not work, if you original method needs an array to be passed. I will probably extends the approach in the future to work with ranges as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jthoenes.net/2009/02/03/argument-fun-with-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

