Algorithm-RandomPointGenerator

 view release on metacpan or  search on metacpan

lib/Algorithm/RandomPointGenerator.pm  view on Meta::CPAN

    $|++;
    my $self = shift;
    die "\nyou must first call read_file_for_bounding_box() before you can call\n" .   
        "metropolis_hastings()$!\n" unless $self->{_bounding_box};
    die "\nyou must first call normalize_input_histogram() before you can call\n" .
        "metropolis_hastings()$!\n" unless $self->{_normalized_input_hist};
    die "\nyou must first call set_sigmas_for_proposal_density() before you can call\n" .
        "metropolis_hastings()$!\n" unless $self->{_sigmax_for_proposal_density};
    my $box = $self->{_bounding_box};
    my $N_discard = $self->{_how_many_to_discard};
    my $N_iterations = $self->{_N} + $N_discard;
    my $sample = [$box->[0][0] + ($box->[0][1] - $box->[0][0]) / 2.0,
                  $box->[1][0] + ($box->[1][1] - $box->[1][0]) / 2.0];
    while ($self->desired_density($sample) == 0) {
        $sample = [$self->{_bounding_box}->[0][0] +
             random_uniform() * ($self->{_bounding_box}->[0][1] - $self->{_bounding_box}->[0][0]),
                   $self->{_bounding_box}->[1][0] +
             random_uniform() * ($self->{_bounding_box}->[1][1] - $self->{_bounding_box}->[1][0])]
    }
    print "\nstarting sample: @$sample\n" unless $self->{_command_line_mode};
    if ($self->{_command_line_mode}) {
        print "\nThe Metropolis-Hastings algorithm will be run over 2500 iterations.\n" .
              "Of the 2500 points generated, the first 500 will be discarded.\n" .
              "Each dot shown below stands for 50 iterations of the algorithm.\n\n";
    } else {
        print "\nThe Metropolis-Hastings algorithm will be run for $N_discard more iterations\n" .
              "than the number of points you requested.  The first $N_discard initial points thus\n" .
              "generated will be discarded from the final output.\n\n";
    }
    my @arr;
    foreach my $i (0..$N_iterations-1) {
        unless ($self->{_command_line_mode}) {
            print "\nIteration number: $i  (out of $N_iterations)\n" if $i % ($N_iterations / 10) == 0;
        }
        print ". " if $i % 50 == 0;
        # Get proposal probability q( $y | $x ).
        my ($newsample, $prob) = $self->get_sample_using_proposal( $sample ); 
        my $a1 = $self->desired_density( $newsample ) / $self->desired_density( $sample );
        my $a2 = $self->proposal_density( $sample, $newsample ) / $prob;
        my $a = $a1 * $a2;
        my $u = random_uniform();
        if ( $a >= 1 ) {
            $sample = $newsample;
            push @arr, $sample;
        } elsif ($u < $a) {
            $sample = $newsample;
            push @arr, $sample;
        } else {
            push @arr, $sample;
        }
    }
    print "\nTotal number of iterations run: $N_iterations\n\n" unless $self->{_command_line_mode};
    $self->{_generated_points} = \@arr;
}

# From the standpoint of matching the input histogram, the quality of the random
# points generated by the Metropolis-Hastings algorithm is affected by what sort of a
# probability distribution is used for the proposal density function.  This module
# uses a bivariate Gaussian density function for this purpose whose widths along x
# and y are controlled by constructor parameter "proposal_density_width" that
# defaults to 0.1.  The function here sets the values for the sigmax and sigmay
# parameters of this bivariate density.



( run in 0.667 second using v1.01-cache-2.11-cpan-96521ef73a4 )