Algorithm-GoldenSection

 view release on metacpan or  search on metacpan

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

package Algorithm::GoldenSection;

use warnings;
use strict;
use Carp;
use Readonly;

use version; our $VERSION = qv('0.0.2');

=head1 NAME

Algorithm::GoldenSection - Golden Section Search Algorithm for one-dimensional minimisation.

=cut
=head1 VERSION

This document describes Algorithm::GoldenSection version 0.0.2

=cut
=head1 DESCRIPTION

This module is an implementation of the Golden Section Search Algorithm for finding minima of a unimodal function. 
In order to isolate a minimum of a univariate functions the minimum must first be isolated. 
Consequently the program first bounds a minimum - i.e. the program initially creates a triplet of points: 
x_low < x_int < x_high, such that f(x_int) is lower than both f(x_low) and f(x_high). Thus we ensure that there 
is a local minimum within the interval: x_low-x_high. The program then uses the Golde Section Search algorithm 
to successively narrow down on the bounded region to find the minimum. 
See http://en.wikipedia.org/wiki/Golden_section_search and
http://www.gnu.org/software/gsl/manual/html_node/One-dimensional-Minimization.html.

The module provides a Perl5OO interface. Simply construct a Algorithm::GoldenSection object with appropriate parameters
- see L</SYNOPSIS>. Then call the minimise C<method>. This returns a LIST of the value of x at the minimum, the value of
f(x) at the minimum and the number of iterations used to isolate the minimum.

=cut
=head1 SYNOPSIS

    use Algorithm::GoldenSection;
    
    # Create a Algorithm::GoldenSection object and pass it a CODE reference to the function to be minimised and initials values for x_low and x_int.
    $gs = Algorithm::GoldenSection->new( { function => sub { my $x = shift; my $b =  $x * sin($x) - 2 * cos($x); return $b },
                                        x_low    => 4,
                                        x_int    => 4.7,} ) ;
    
    # Call minimisation method to bracket and minimise.
    my ($x_min, $f_min, $iterations) = $gs->minimise;

    print qq{\nMinimisation results: x a minimum = $x_min, function value at minimum = $f_min. Calculation took $iterations iterations};

=cut

# package-scoped lexicals
Readonly::Scalar my $ouro => 1.618034 ;
Readonly::Scalar my $glimite => 100.0 ;
Readonly::Scalar my $pequeninho => 1.0e-20 ;
Readonly::Scalar my $tolerancia => 3.0e-8;  # tolerance
Readonly::Scalar my $C => (3-sqrt(5))/2;
Readonly::Scalar my $R => 1-$C;

#/ I had leaving things for operator precedence. you won´t see A+B*(C-D) whe you mean: A+( B*(C-D) ) - i.e. * binds more tightly that +

sub new {
    my ( $class, $h_ref ) = @_;
    croak qq{\nArguments must be passed as HASH reference.} if ( ( $h_ref ) && ( ref $h_ref ne q{HASH} ) );
    my $self = {};
    bless $self, $class;
    $self->_check_options($h_ref);
    return $self;
}

sub _check_options {

    my ( $self, $h_ref ) = @_;

    croak qq{\nOption \x27function\x27 is obrigatory and accepts a CODE reference} 
      if ( ( !exists $h_ref->{function} ) || ( ref $h_ref->{function} ne q{CODE} ) );
    croak qq{\nOption \x27x_low\x27 requirements a numeric value} 
      if ( ( !exists $h_ref->{x_low} ) || ( $h_ref->{x_low} !~ /\A[+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?\z/xms ) );
    croak qq{\nOption \x27x_low\x27 requirements a numeric value} 
      if ( ( !exists $h_ref->{x_int} ) || ( $h_ref->{x_int} !~ /\A[+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?\z/xms ) );

    $self->{function} = $h_ref->{function};
    $self->{x_low} = $h_ref->{x_low};
    $self->{x_int} = $h_ref->{x_int};

}

sub _switch {



( run in 0.677 second using v1.01-cache-2.11-cpan-39bf76dae61 )