AI-SimulatedAnnealing
view release on metacpan or search on metacpan
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
# 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
# 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
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,
( run in 0.287 second using v1.01-cache-2.11-cpan-4d50c553e7e )