AI-SimulatedAnnealing
view release on metacpan or search on metacpan
lib/AI/SimulatedAnnealing.htm view on Meta::CPAN
power of the precision.</p>
<p>The initial temperature is the size of the largest range after the
bounds have been converted to integers. During each temperature
reduction, the <code>anneal()</code> function multiplies the
temperature by 0.95 and then rounds the result down to the nearest
integer (if the result isn't already an integer). When the
temperature reaches zero, annealing is immediately terminated.</p>
<p style="margin-left: 13px;"><b>Note:</b> Annealing can sometimes
complete before the temperature reaches zero if, after a particular
temperature reduction, a brute-force optimization approach (that is,
testing every possible combination of numbers within the subranges
determined by the new temperature) would produce a number of tests
that is less than or equal to the specified cycles per temperature.
In that case, the <code>anneal()</code> function performs the
brute-force optimization to complete the annealing process.</p>
<p>After a temperature reduction, the <code>anneal()</code> function
determines each new subrange such that the current optimal integer
from the total range is as close as possible to the center of the new
subrange. When there is a tie between two possible positions for the
subrange within the total range, a "coin flip" decides.</p>
<hr/>
<h1><a name="prerequisites">PREREQUISITES</a></h1>
<p>This module requires Perl 5, version 5.10.1 or later.</p>
<hr/>
<h1><a name="methods">METHODS</a></h1>
<dl>
<dt><strong><a class="item" name="anneal">anneal($number_specs,
$cost_function, $cycles_per_temperature);</a></strong></dt>
<dd>
<p>The <code>anneal()</code> function takes a reference to an array
lib/AI/SimulatedAnnealing.pm view on Meta::CPAN
# The anneal() function takes a reference to an array of number
# specifications (which are references to hashes containing "LowerBound",
# "UpperBound", and "Precision" fields), a reference to a cost function
# (which takes a list of numbers matching the specifications and returns a
# number representing a cost to be minimized), and a positive integer
# specifying the number of randomization cycles to perform at each
# temperature during the annealing process.
#
# The function returns a reference to an array containing the
# optimized list of numbers.
sub anneal {
my $number_specs = validate_number_specs($_[0]);
my $cost_function = $_[1];
my $cycles_per_temperature = $_[2];
my $current_temperature;
my $lowest_cost;
my @integral_lower_bounds;
my @integral_upper_bounds;
my @optimized_list;
lib/AI/SimulatedAnnealing.pm view on Meta::CPAN
@optimized_list = @candidate_list;
} # end unless
} # next cycle
# Reduce the temperature:
$current_temperature = floor(
$current_temperature * $TEMPERATURE_MULTIPLIER);
} # end while
return \@optimized_list;
} # end sub
####
# Private helper functions for use by this module:
# The use_brute_force() function takes a reference to an array of number
# specifications (which are references to hashes containing "LowerBound",
# "UpperBound", and "Precision" fields) and a reference to a cost function
# (which takes a list of numbers matching the specifications and returns a
# number representing a cost to be minimized). The method tests every
# possible combination of numbers matching the specifications and returns a
# reference to an array containing the optimal numbers, where "optimal"
# means producing the lowest cost.
sub use_brute_force {
my $number_specs = validate_number_specs($_[0]);
my $cost_function = $_[1];
my @optimized_list;
my @lists;
my @cursors;
# Populate the list of lists of numbers:
for my $number_spec (@{ $number_specs }) {
my @list;
lib/AI/SimulatedAnnealing.pm view on Meta::CPAN
last;
}
else {
$cursors[$dex] = 0;
} # end if
} # next $dex
} until ($finished);
# Return the result:
return \@optimized_list;
} # end sub
# The validate_number_specs() function takes a reference to an array of
# number specifications (which are references to hashes with "LowerBound",
# "UpperBound", and "Precision" fields) and returns a reference to a version
# of the array in which bounds with higher precision than that specified
# have been rounded inward. If a number specification is not valid, the
# function calls "die" with an error message.
sub validate_number_specs {
my $raw_number_specs = $_[0];
my @processed_number_specs = @{ $raw_number_specs };
for my $number_spec (@processed_number_specs) {
my $lower_bound = $number_spec->{"LowerBound"};
my $upper_bound = $number_spec->{"UpperBound"};
my $precision = $number_spec->{"Precision"};
unless (looks_like_number($precision)
&& int($precision) == $precision
lib/AI/SimulatedAnnealing.pm view on Meta::CPAN
my $integral_lower_bound = ceil( $lower_bound * (10 ** $precision));
my $integral_upper_bound = floor($upper_bound * (10 ** $precision));
$number_spec->{"LowerBound"}
= $integral_lower_bound / (10 ** $precision);
$number_spec->{"UpperBound"}
= $integral_upper_bound / (10 ** $precision);
} # next $number_spec
return \@processed_number_specs;
} # end sub
# Module return value:
1;
__END__
=head1 NAME
AI::SimulatedAnnealing - optimize a list of numbers according to a specified
cost function.
lib/AI/SimulatedAnnealing.pm view on Meta::CPAN
The initial temperature is the size of the largest range after the
bounds have been converted to integers. During each temperature
reduction, the anneal() function multiplies the temperature by 0.95
and then rounds the result down to the nearest integer (if the result
isn't already an integer). When the temperature reaches zero,
annealing is immediately terminated.
NOTE: Annealing can sometimes complete before the temperature
reaches zero if, after a particular temperature reduction, a
brute-force optimization approach (that is, testing every possible
combination of numbers within the subranges determined by the new
temperature) would produce a number of tests that is less than or
equal to the specified cycles per temperature. In that case, the
anneal() function performs the brute-force optimization to complete
the annealing process.
After a temperature reduction, the anneal() function determines each
new subrange such that the current optimal integer from the total
range is as close as possible to the center of the new subrange.
When there is a tie between two possible positions for the subrange
within the total range, a "coin flip" decides.
=head1 PREREQUISITES
This module requires Perl 5, version 5.10.1 or later.
=head1 METHODS
=over
t/annealing_tests.t view on Meta::CPAN
my @number_specs;
push @number_specs,
{"LowerBound" => 1.9, "UpperBound" => 4, "Precision" => 0};
push @number_specs,
{"LowerBound" => 0.0, "UpperBound" => 2, "Precision" => 0};
push @number_specs,
{"LowerBound" => -4.0, "UpperBound" => 8, "Precision" => 0};
$abc = anneal(\@number_specs,
sub {
my $nums = $_[0];
my $range = max(@{ $nums }) - min(@{ $nums });
my $val = ($nums->[0] * 9) + ($nums->[1] * 3) + $nums->[2];
my $cost = $range + (10 * abs(23 - $val));
return $cost;
}, 120);
say "\nHere are a, b, and c: " . $abc->[0] . ", "
. $abc->[1] . ", " . $abc->[2];
t/annealing_tests.t view on Meta::CPAN
# The cost_function_factory() takes a reference to an array containing
# real-world market distances and returns a reference to a cost function.
# The cost function takes a reference to an array of three coefficients,
# and returns the mean absolute percentage deviation of the calculated
# results from the real-world results based on this formula:
#
# (a * sqrt(x + b)) + c
#
# where x is a number of trading days in the range 3 to 63.
sub cost_function_factory {
my $real_world_distances = $_[0];
my $current_coefficients;
my $calculate_distance
= sub {
my $trading_days = $_[0];
my $distance = ($current_coefficients->[0]
* sqrt($trading_days + $current_coefficients->[1]))
+ $current_coefficients->[2];
return $distance;
};
my $cost_function
= sub {
my $coefficients = $_[0];
my @calculated_distances;
my $cumulative_deviation;
my $cost;
$current_coefficients = $coefficients;
for my $trading_days (3..63) {
push @calculated_distances,
t/annealing_tests.t view on Meta::CPAN
- $real_world_distances->[$dex])
/ $real_world_distances->[$dex]);
} # next $dex
$cost = $cumulative_deviation / 61;
return $cost;
};
return $cost_function;
} # end sub
( run in 0.638 second using v1.01-cache-2.11-cpan-88abd93f124 )