Forum: Ruby what is happening here

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
George G. (Guest)
on 2009-04-08 16:01
i have some perl code

while ($high - $low > 0.001) {    # precision
    # calculate the sum of all normalized scores
    my $sum = Pn * Pn * exp($lambda * $match)    * 4
            + Pn * Pn * exp($lambda * $mismatch) * 12;
    # refine guess at lambda
    if ($sum > 1) {
        $high = $lambda;
        $lambda = ($lambda + $low)/2;
    }
    else {
        $low = $lambda;
        $lambda = ($lambda + $high)/2;
    }
}


trying to rewrite this in ruby
while (high - low > 0.001)
  #calculate the sum of all normalized scores
  sum = Pn * Pn **(lambda * match) * 4 + Pn * Pn **(lambda * mismatch) *
12

  #refine guess at lambda
  if sum > 1
    high = lambda
    lambda = (lambda  + low)/2
  else
    low = lambda
    lambda = (lambda+high)/2
  end
end

Is this the right way?

i seem to get different results when i execute the ruby version.
any ideas?
Matthias R. (Guest)
on 2009-04-08 16:32
(Received via mailing list)
George G. wrote:
>   sum = Pn * Pn **(lambda * match) * 4 + Pn * Pn **(lambda * mismatch) *
> 12

It seems like you're using the ** operator wrong.  You should use Ruby's
Math.exp instead (which is the direct equivalent to Perl's exp).

-Matthias
George G. (Guest)
on 2009-04-08 16:57
> It seems like you're using the ** operator wrong.  You should use Ruby's
> Math.exp instead (which is the direct equivalent to Perl's exp).
>
> -Matthias

Thank you Mat
i have changed that. here is the full script in ruby:
Pn = 0.25 #probabilty of any nuclotide

match = 10
mismatch = -10

expected_score = match * 0.25 + mismatch * 0.75
 if match <=0 or expected_score >= 0
   puts "illegal scores"
#   quit
 end

#calculate lambda
#initial estimates
lambda = 1
high      = 2
low        = 0


while (high - low > 0.001) do
  #calculate the sum of all normalized scores
  sum = Pn * Pn * Math.exp(lambda * match) * 4 + Pn * Pn *
Math.exp(lambda * mismatch) * 12

  #refine guess at lambda
  if sum > 1
    high = lambda
    lambda = (lambda  + low)/2
  else
    low = lambda
    lambda = (lambda+high)/2
  end
end

  #compute target frequencies and H
  target_id = Pn * Pn * Math.exp(lambda * match) * 4
   h = lambda * match * target_id + lambda * mismatch * (1 - target_id)

puts "expected_score #{expected_score}\n"
puts "lambda: #{lambda} nats, #{lambda/Math.log(2)} bits"
puts "H: #{h} nats , #{h/Math.log(2)} bits"
puts "%ID: #{target_id * 100}"


and the original perl script is here:
#!/usr/bin/perl -w use strict;
use constant Pn => 0.25; # probability of any nucleotide

die "usage: $0 <match> <mismatch>\n" unless @ARGV == 2;

my ($match, $mismatch) = @ARGV;

my $expected_score = $match * 0.25 + $mismatch * 0.75;
die "illegal scores\n" if $match <= 0 or $expected_score >= 0;


# calculate lambda
my ($lambda, $high, $low) = (1, 2, 0); # initial estimates

while ($high - $low > 0.001) {         # precision
    # calculate the sum of all normalized scores
    my $sum = Pn * Pn * exp($lambda * $match)    * 4
            + Pn * Pn * exp($lambda * $mismatch) * 12;
    # refine guess at lambda
    if ($sum > 1) {
        $high = $lambda;
        $lambda = ($lambda + $low)/2;
    }
    else {
        $low = $lambda;
        $lambda = ($lambda + $high)/2;
    }
}


# compute target frequency and H
my $targetID = Pn * Pn * exp($lambda * $match) * 4;
my $H = $lambda * $match    *     $targetID
      + $lambda * $mismatch * (1 -$targetID);


# output
print "expscore: $expected_score\n";
print "lambda:   $lambda nats (", $lambda/log(2), " bits)\n";
print "H:        $H nats (", $H/log(2), " bits)\n";
print "%ID:      ", $targetID * 100, "\n";


The ruby version seems to get into an infinite loop. while the perl
version executes nicely and with the expected results.
Fritz Heinrichmeyer (Guest)
on 2009-04-08 17:25
(Received via mailing list)
in ruby lambda, high and low are integers and divide by two is also
integer arithmetic. Perl uses float for scalars by default.


Am Mittwoch, den 08.04.2009, 07:57 -0500 schrieb George G.:
Peter Z. (Guest)
on 2009-04-08 17:32
(Received via mailing list)
Quoting George G. <removed_email_address@domain.invalid>:

>     }
>     else {
>         $low = $lambda;
>         $lambda = ($lambda + $high)/2;
>     }
> }
>

Pn * exp($lambda * $match) is Pn * (Math::E ** (lambda + match)), not
Pn ** (lambda + match).

   WBR, Peter Z.
Fritz Heinrichmeyer (Guest)
on 2009-04-09 11:27
(Received via mailing list)
define lambda, high and low as floats, lambda = 1.0, high=2.0, low = 0.0


Am Mittwoch, den 08.04.2009, 07:57 -0500 schrieb George G.:
George G. (Guest)
on 2009-04-09 12:33
Fritz Heinrichmeyer wrote:
> define lambda, high and low as floats, lambda = 1.0, high=2.0, low = 0.0

Thank you so much everyone for your responses, it works nicely now!

GG
This topic is locked and can not be replied to.