AI-Pathfinding-OptimizeMultiple

 view release on metacpan or  search on metacpan

META.json  view on Meta::CPAN

                     }
                  ],
                  "include_underscores" : 0
               },
               "Dist::Zilla::Role::MetaProvider::Provider" : {
                  "$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004",
                  "inherit_missing" : 1,
                  "inherit_version" : 1,
                  "meta_noindex" : 1
               },
               "Dist::Zilla::Role::ModuleMetadata" : {
                  "Module::Metadata" : "1.000037",
                  "version" : "0.006"
               }
            },
            "name" : "@Filter/MetaProvides::Package",
            "version" : "2.004003"
         },
         {
            "class" : "Dist::Zilla::Plugin::MetaResources",
            "name" : "@Filter/MetaResources",
            "version" : "6.024"

META.yml  view on Meta::CPAN

            -
              class: Dist::Zilla::Plugin::FinderCode
              name: '@Filter/MetaProvides::Package/AUTOVIV/:InstallModulesPM'
              version: '6.024'
          include_underscores: 0
        Dist::Zilla::Role::MetaProvider::Provider:
          $Dist::Zilla::Role::MetaProvider::Provider::VERSION: '2.002004'
          inherit_missing: '1'
          inherit_version: '1'
          meta_noindex: '1'
        Dist::Zilla::Role::ModuleMetadata:
          Module::Metadata: '1.000037'
          version: '0.006'
      name: '@Filter/MetaProvides::Package'
      version: '2.004003'
    -
      class: Dist::Zilla::Plugin::MetaResources
      name: '@Filter/MetaResources'
      version: '6.024'
    -
      class: Dist::Zilla::Plugin::ModuleBuild
      config:

bin/optimize-game-ai-multi-tasking  view on Meta::CPAN

optimize-game-ai-multi-tasking - command line driver for L<AI::Pathfinding::OptimizeMultiple>

=head1 VERSION

version 0.0.17

=head1 DESCRIPTION

To be written.

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN

use AI::Pathfinding::OptimizeMultiple::SimulationResults ();

use MooX qw/late/;

use PDL;
use Scalar::Util qw/ blessed /;

has chosen_scans     => ( isa => 'ArrayRef', is => 'rw' );
has _iter_idx        => ( isa => 'Int', is => 'rw', default  => sub { 0; }, );
has _num_boards      => ( isa => 'Int', is => 'ro', init_arg => 'num_boards', );
has _orig_scans_data => ( isa => 'PDL', is => 'rw' );
has _optimize_for => ( isa => 'Str', is => 'ro', init_arg => 'optimize_for', );
has _scans_data   => ( isa => 'PDL', is => 'rw' );
has _selected_scans =>
    ( isa => 'ArrayRef', is => 'ro', init_arg => 'selected_scans', );
has _status => ( isa => 'Str',           is => 'rw' );
has _quotas => ( isa => 'ArrayRef[Int]', is => 'ro', init_arg => 'quotas' );
has _total_boards_solved => ( isa => 'Int', is => 'rw' );
has _total_iters         => ( is  => 'rw' );
has _trace_cb =>
    ( isa => 'Maybe[CodeRef]', is => 'ro', init_arg => 'trace_cb' );
has _scans_meta_data => ( isa => 'ArrayRef', is => 'ro', init_arg => 'scans' );
has _scans_iters_pdls =>
    ( isa => 'HashRef', is => 'rw', init_arg => 'scans_iters_pdls' );
has _stats_factors => (
    isa      => 'HashRef',
    is       => 'ro',
    init_arg => 'stats_factors',
    default  => sub { return +{}; },
);

sub BUILD
{
    my $self = shift;

    my $args = shift;

    my $scans_data = PDL::cat(
        map {
            my $id     = $_->id();
            my $pdl    = $self->_scans_iters_pdls()->{$id};
            my $factor = $self->_stats_factors->{$id};
            (
                defined($factor)
                ? ( ( $pdl >= 0 ) * ( ( $pdl / $factor )->ceil() ) +
                        ( $pdl < 0 ) * $pdl )
                : $pdl
            );
        } @{ $self->_selected_scans() }
    );

    $self->_orig_scans_data($scans_data);
    $self->_scans_data( $self->_orig_scans_data()->copy() );

    return 0;
}

my $BOARDS_DIM     = 0;
my $SCANS_DIM      = 1;
my $STATISTICS_DIM = 2;

sub _next_iter_idx
{

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN

    {
        my $q_more = $self->_get_next_quota();
        if ( !defined($q_more) )
        {
            AI::Pathfinding::OptimizeMultiple::Error::OutOfQuotas->throw(
                error => "No q_more", );
        }

        $iters_quota += $q_more;

        my $iters        = $self->_scans_data()->slice(":,:,0");
        my $solved       = ( ( $iters <= $iters_quota ) & ( $iters > 0 ) );
        my $num_moves    = $self->_scans_data->slice(":,:,2");
        my $solved_moves = $solved * $num_moves;

        my $solved_moves_sums   = _my_sum_over($solved_moves);
        my $solved_moves_counts = _my_sum_over($solved);
        my $solved_moves_avgs   = $solved_moves_sums / $solved_moves_counts;

        ( undef, undef, $selected_scan_idx, undef ) =
            $solved_moves_avgs->minmaximum();

        $num_solved_in_iter = $solved_moves_counts->at($selected_scan_idx);

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN

    {
        my $q_more = $self->_get_next_quota();
        if ( !defined($q_more) )
        {
            AI::Pathfinding::OptimizeMultiple::Error::OutOfQuotas->throw(
                error => "No q_more", );
        }

        $iters_quota += $q_more;

        my $iters        = $self->_scans_data()->slice(":,:,0");
        my $solved       = ( ( $iters <= $iters_quota ) & ( $iters > 0 ) );
        my $num_moves    = $self->_scans_data->slice(":,:,2");
        my $solved_moves = $solved * $num_moves;

        my $solved_moves_maxima = $solved_moves->maximum()->slice(":,(0),(0)");
        my $solved_moves_counts = _my_sum_over($solved);

        ( undef, undef, $selected_scan_idx, undef ) =
            $solved_moves_maxima->minmaximum();

        $num_solved_in_iter = $solved_moves_counts->at($selected_scan_idx);
    }

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN

        {
            AI::Pathfinding::OptimizeMultiple::Error::OutOfQuotas->throw(
                error => "No q_more" );
        }

        $iters_quota += $q_more;

        ( undef, $num_solved_in_iter, undef, $selected_scan_idx ) =
            PDL::minmaximum(
            PDL::sumover(
                ( $self->_scans_data() <= $iters_quota ) &
                    ( $self->_scans_data() > 0 )
            )
            );
    }

    return {
        quota      => $iters_quota,
        num_solved => $num_solved_in_iter->at(0),
        scan_idx   => $selected_scan_idx->at(0),
    };
}

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN

        }
    }

    return;
}

sub _get_num_scans
{
    my $self = shift;

    return ( ( $self->_scans_data()->dims() )[$SCANS_DIM] );
}

sub _calc_chosen_scan
{
    my ( $self, $selected_scan_idx, $iters_quota ) = @_;

    return AI::Pathfinding::OptimizeMultiple::ScanRun->new(
        {
            iters => (
                $iters_quota * (

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN

    $self->_status("iterating");

    my $iters_quota      = 0;
    my $flares_num_iters = PDL::Core::pdl( [ (0) x $self->_get_num_scans() ] );
    my $ones_constant =
        PDL::Core::pdl( [ map { [1] } ( 1 .. $self->_get_num_scans() ) ] );

    my $next_num_iters_for_each_scan_x_scan =
        ( ( $ones_constant x $flares_num_iters ) );

    my $num_moves = $self->_scans_data->slice(":,:,1");

    # The number of moves for dimension 0,1,2 above.
    my $num_moves_repeat = $num_moves->clump( 1 .. 2 )->xchg( 0, 1 )
        ->dummy( 0, $self->_get_num_scans() );

    my $selected_scan_idx;

    my $loop_iter_num = 0;

    my $UNSOLVED_NUM_MOVES_CONSTANT = 64 * 1024 * 1024;

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN

        # Next number of iterations for each scan x scan combination.
        my $next_num_iters = (
            ( $ones_constant x $flares_num_iters ) + (
                PDL::MatrixOps::identity( $self->_get_num_scans() ) *
                    $iters_quota
            )
        );

        # print "\$next_num_iters = $next_num_iters\n";

        my $iters = $self->_scans_data()->slice(":,:,0");

        my $iters_repeat =
            $iters->dummy( 0, $self->_get_num_scans() )->xchg( 1, 2 )
            ->clump( 2 .. 3 );

        # print "\$iters_repeat =", join(",",$iters_repeat->dims()), "\n";

        my $next_num_iters_repeat =
            $next_num_iters->dummy( 0, $self->_num_boards() )->xchg( 0, 2 );

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN

    }
}

sub calc_board_iters
{
    my $self  = shift;
    my $board = shift;

    my $board_iters = 0;

    my @info      = PDL::list( $self->_orig_scans_data()->slice("$board,:") );
    my @orig_info = @info;

    foreach my $s ( @{ $self->chosen_scans() } )
    {
        if (   ( $info[ $s->scan_idx() ] > 0 )
            && ( $info[ $s->scan_idx() ] <= $s->iters() ) )
        {
            $board_iters += $info[ $s->iters() ];
            last;
        }

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN


    if ( $board_idx !~ /\A[0-9]+\z/ )
    {
        die "Board index '$board_idx' is not numeric!";
    }

    $args ||= {};

    my $chosen_scans = ( $args->{chosen_scans} || $self->chosen_scans );

    my @info = PDL::list( $self->_orig_scans_data()->slice("$board_idx,:") );

    my $board_iters = 0;

    my @scan_runs;

    my $status = "Unsolved";

    my $add_new_scan_run = sub {
        my $scan_run = shift;

lib/AI/Pathfinding/OptimizeMultiple.pm  view on Meta::CPAN


=head1 AUTHOR

Shlomi Fish, L<http://www.shlomifish.org/> .

=head1 ACKNOWLEDGEMENTS

B<popl> from Freenode's #perl for trying to dig some references to an existing
algorithm in the scientific literature.

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

lib/AI/Pathfinding/OptimizeMultiple/App/CmdLine.pm  view on Meta::CPAN

=head2 $self->run_flares()

For internal use.

=head2 $self->argv()

An array ref of command line arguments.

=head2 $self->input_obj_class()

The class to handle the input data - by default -
L<AI::Pathfinding::OptimizeMultiple::DataInputObj>.

=head2 BUILD()

Moo leftover. B<INTERNAL USE>.

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

lib/AI/Pathfinding/OptimizeMultiple/DataInputObj.pm  view on Meta::CPAN

    return ( ( !@proc_stat ) || ( $orig_stat[9] > $proc_stat[9] ) );
}

# Number of numbers in the header of the solutions' iteration counts
my $NUM_NUMBERS_IN_HEADER = 3;

my $HEADER_START_BOARD_IDX  = 0;
my $HEADER_NUM_BOARDS       = 1;
my $HEADER_ITERATIONS_LIMIT = 2;

sub _get_scans_data_helper
{
    my $self = shift;

    my $selected_scans = $self->selected_scans();

    my $start_board = $self->start_board();

    my $scans_data      = {};
    my $scans_lens_data = {};

    my $data_dir = ".data-proc";
    my $lens_dir = ".data-len-proc";

    mkpath( [ $data_dir, $lens_dir ] );

    foreach my $scan (@$selected_scans)
    {
        {
            my $dest_path = $data_dir . "/" . $scan->id();
            {
                if (
                    $self->_should_update(
                        $scan->data_file_path(), $dest_path
                    )
                    )
                {
                    my $data_s = _slurp( $scan->data_file_path() );
                    my @array  = unpack( "l*", $data_s );
                    if (   ( $array[$HEADER_START_BOARD_IDX] != 1 )
                        || ( $array[$HEADER_NUM_BOARDS] < $self->num_boards ) )
                    {
                        die "Incorrect file format in scan "
                            . $scan->{'id'} . "!\n";
                    }

                    my $c = pdl( \@array );

                    writefraw( $c, $dest_path );
                }
            }
            {
                my $start_idx = $NUM_NUMBERS_IN_HEADER + ( $start_board - 1 );
                my $scan_vec  = readfraw($dest_path);
                $scans_data->{ $scan->id() } =
                    $scan_vec->slice( $start_idx . ":"
                        . ( $start_idx + $self->num_boards() - 1 ) );
            }
        }
        {
            my $src  = $scan->data_file_path();
            my $dest = "$lens_dir/" . $scan->id();

            if ( $self->_should_update( $src, $dest ) )
            {
                my $data_s = _slurp($src);

                my @iters = unpack( "l*", $data_s );
                if ( ( $iters[0] != 1 ) || ( $iters[1] < $self->num_boards() ) )
                {
                    die "Incorrect file format in scan " . $scan->id() . "!\n";
                }

                # Remove the header
                splice @iters, 0, $NUM_NUMBERS_IN_HEADER;

                my $c = pdl(
                    [
                        \@iters,
                        $self->_read_text_ints_file(
                            "data/" . $scan->id() . ".fcs.moves.txt"
                        ),
                        $self->_read_text_ints_file(
                            "data/" . $scan->id() . ".fcpro.moves.txt"
                        ),
                    ]
                );

                writefraw( $c, $dest );
            }
            {
                my $scan_vec = readfraw($dest);
                $scans_lens_data->{ $scan->id() } = $scan_vec->slice(
                    sprintf( "%d:%d,:,*",
                        ( $start_board - 1 ),
                        ( ( $self->num_boards() - 1 ) + ( $start_board - 1 ) ) )
                )->xchg( 1, 2 );
            }
        }
    }

    return { 'scans' => $scans_data, 'with_lens' => $scans_lens_data };
}

sub _get_scans_data_generic
{
    my ( $self, $id ) = @_;

    return $self->_get_scans_data_helper()->{$id};
}

sub get_scans_iters_pdls
{
    my $self = shift;

    return $self->_get_scans_data_generic('scans');
}

sub get_scans_lens_iters_pdls
{
    my $self = shift;

    return $self->_get_scans_data_generic('with_lens');
}

sub _filter_scans_based_on_black_list_ids
{
    my ( $scans, $black_list_ids ) = @_;

    my %black_list = ( map { /(\d+)/ ? ( $1 => 1 ) : () } @$black_list_ids );

    return [ grep { !exists( $black_list{ $_->id() } ) } @$scans ];
}

sub _is_scan_suitable
{
    my ( $self, $scan ) = @_;

    my @stat = stat( $scan->data_file_path() );
    return (
        scalar(@stat)
            && ( $stat[7] >=
            12 + ( $self->num_boards() + $self->start_board() - 1 ) * 4 )
    );
}

sub _get_scans_registry_file_path
{
    return "scans.txt";

lib/AI/Pathfinding/OptimizeMultiple/DataInputObj.pm  view on Meta::CPAN


    return [
        qw(freecell-solver-fc-pro-range-solve),
        $min_board,
        $max_board,
        "20",
        @variant,
        '--total-iterations-limit',
        ( $ENV{FC_SOLVE_RANGE_ITERS_LIMIT} // 100000 ),
        '--binary-output-to',
        "data/$id.data.bin",
        @$argv,
        @fc_num,
    ];
}

sub time_scan
{
    my $self = shift;
    my $args = shift;

    my $min_board = $args->{'min'} || 1;
    my $max_board = $args->{'max'} || 32_000;
    my $id        = $args->{'id'};

    my $cmd_line = $self->_get_scan_cmd_line($args);

    open my $from_cmd, "-|", @$cmd_line
        or die "Could not start '@$cmd_line'";
    open my $fcs_out,    ">", "data/$id.fcs.moves.txt";
    open my $fc_pro_out, ">", "data/$id.fcpro.moves.txt";
    $fcs_out->autoflush(1);
    $fc_pro_out->autoflush(1);
    while ( my $line = <$from_cmd> )
    {
        print $line;
        chomp($line);
        if ( $line =~ m{\A\[\[Num FCS Moves\]\]=(.*)\z}o )
        {
            print {$fcs_out} "$1\n";
        }

lib/AI/Pathfinding/OptimizeMultiple/DataInputObj.pm  view on Meta::CPAN

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

AI::Pathfinding::OptimizeMultiple::DataInputObj - handle the data input.

=head1 VERSION

version 0.0.17

=head1 SUBROUTINES/METHODS

=head2 $self->get_next_id()

Retrieves the next scan ID and increment it.

lib/AI/Pathfinding/OptimizeMultiple/DataInputObj.pm  view on Meta::CPAN


=head2 $self->get_scan_ids_aref()

Get an array reference of the scan IDs.

=head2 my $idx = $self->lookup_scan_idx_based_on_id($scan_id)

$scan_id is a string and lookup_scan_idx_based_on_id() looks up its index
in the scans.

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

lib/AI/Pathfinding/OptimizeMultiple/IterState.pm  view on Meta::CPAN

sub detach
{
    my $self = shift;
    $self->_main(undef);
}

sub idx_slice
{
    my $self = shift;

    my $scans_data = $self->_main()->_scans_data();

    my @dims = $scans_data->dims();

    return $scans_data->slice(
        join( ",", ":", $self->_scan_idx(), ( ("(0)") x ( @dims - 2 ) ) ) );
}

sub update_total_iters
{
    my $state = shift;

    # $r is the result of this scan.
    my $r = $state->idx_slice();

lib/AI/Pathfinding/OptimizeMultiple/IterState.pm  view on Meta::CPAN

    # Find all the states that weren't solved.
    my $indexes = PDL::which( ( $r > $state->_quota() ) | ( $r < 0 ) );

    # Add the iterations for all the states that have not been solved
    # yet.
    $state->_main()
        ->_add_to_total_iters( $indexes->nelem() * $state->_quota() );

    # Keep only the states that have not been solved yet.
    $state->_main()
        ->_scans_data(
        $state->_main()->_scans_data()->dice( $indexes, "X" )->copy() );
}

sub update_idx_slice
{
    my $state = shift;
    my $r     = $state->idx_slice()->copy();

    # $r cannot be 0, because the ones that were 0, were already solved
    # in $state->update_total_iters().
    my $idx_slice = $state->idx_slice();

lib/AI/Pathfinding/OptimizeMultiple/IterState.pm  view on Meta::CPAN

Internal use.

=head2 $self->update_idx_slice()

Internal use.

=head2 $self->register_params()

Internal use.

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

lib/AI/Pathfinding/OptimizeMultiple/PostProcessor.pm  view on Meta::CPAN

=head1 SUBROUTINES/METHODS

=head2 $self->scans_rle()

For internal use.

=head2 $self->process($scans_orig)

For internal use.

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

lib/AI/Pathfinding/OptimizeMultiple/Scan.pm  view on Meta::CPAN

    my $self = shift;
    $self->used(1);
}

sub is_used
{
    my $self = shift;
    return $self->used();
}

sub data_file_path
{
    my $self = shift;

    return "./data/" . $self->id() . ".data.bin";
}

1;

__END__

=pod

=encoding UTF-8

lib/AI/Pathfinding/OptimizeMultiple/Scan.pm  view on Meta::CPAN

=head1 METHODS

=head2 $self->mark_as_used()

Mark the scan as used.

=head2 $self->is_used()

Returns whether the scan was used.

=head2 $scan->data_file_path()

Returns the path to the data file of the scan, where the numbers of iterations
per board are stored.

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

lib/AI/Pathfinding/OptimizeMultiple/ScanRun.pm  view on Meta::CPAN


=head1 AUTHOR

Shlomi Fish, L<http://www.shlomifish.org/> .

=head1 ACKNOWLEDGEMENTS

B<popl> from Freenode's #perl for trying to dig some references to an existing
algorithm in the scientific literature.

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

lib/AI/Pathfinding/OptimizeMultiple/SimulationResults.pm  view on Meta::CPAN

Returns the status.

=head1 SEE ALSO

L<AI::Pathfinding::OptimizeMultiple> , L<AI::Pathfinding::OptimizeMultiple::ScanRun> .

=head1 AUTHOR

Shlomi Fish, L<http://www.shlomifish.org/> .

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

t/optimize-multiple-full-test.t  view on Meta::CPAN


use Test::More tests => 4;

use Test::Differences qw(eq_or_diff);

use PDL (qw/ pdl /);

use AI::Pathfinding::OptimizeMultiple ();

# TEST:$c=0;
sub test_based_on_data
{
    local $Test::Builder::Level = $Test::Builder::Level + 1;

    my ( $scans_aref, $quotas_aref, $want_results, $stats_factors, $blurb ) =
        @_;

    my $results_aref = [];

    my $selected_scans = [
        map {
            my $id = $_->{name};

            AI::Pathfinding::OptimizeMultiple::Scan->new(
                id       => $id,
                cmd_line => "-l $id",
            )
        } @{$scans_aref},
    ];

    my %num_boards = ( map { scalar( @{ $_->{data} } ) => 1 } @$scans_aref );

    my @nums = keys(%num_boards);
    if ( @nums != 1 )
    {
        Carp::confess("num is not 1.");
    }

    my $obj = AI::Pathfinding::OptimizeMultiple->new(
        {
            scans      => [ map { +{ name => $_->{name} } } @$scans_aref, ],
            num_boards => $nums[0],
            scans_iters_pdls =>
                { map { $_->{name} => pdl( $_->{data} ), } @$scans_aref, },
            quotas         => $quotas_aref,
            selected_scans => $selected_scans,
            optimize_for   => "speed",
            ( $stats_factors ? ( stats_factors => $stats_factors ) : () ),
        }
    );

    $obj->calc_meta_scan();

    my @have = (

t/optimize-multiple-full-test.t  view on Meta::CPAN

                name  => $scans_aref->[ $_->scan_idx ]->{name},
                iters => $_->iters,
            }
        } @{ $obj->chosen_scans() }
    );

    # TEST:$c++;
    return eq_or_diff( \@have, $want_results, "$blurb - (eq_or_diff)", );
}

# TEST:$test_based_on_data=$c;

{
    # TEST*$test_based_on_data
    test_based_on_data(
        [
            {
                name => "first",
                data => [ 200, 400, 500 ],
            },
            {
                name => "second",
                data => [ 300, 50, 1000 ],
            },
            {
                name => "third",
                data => [ 10, 10, 100000 ],
            },
        ],
        [ 200, 500, ],
        [
            {
                name  => "third",
                iters => 200,
            },
            {
                name  => "first",
                iters => 500,
            },
        ],
        undef(),
        'Basic test',
    );
}

{
    # TEST*$test_based_on_data
    test_based_on_data(
        [
            {
                name => "first",
                data => [ 50_000, 100_000, 100_000, 1_000_000, 2_000_000 ],
            },
            {
                name => "second",
                data => [ 100, 200, 200, 300, 300 ],
            },
            {
                name => "third",
                data => [ 2000, 2000, 2000, 2000, 2000 ],
            },
        ],
        [ 100, 300, ],
        [
            {
                name  => "first",
                iters => 100_000,
            },
            {
                name  => "second",

t/optimize-multiple-full-test.t  view on Meta::CPAN

            },
        ],
        {
            first => 1000,
        },
        'Test the stats_factors',
    );
}

{
    # TEST*$test_based_on_data
    test_based_on_data(
        [
            {
                name => "first",
                data => [ 50_000, 99_500, 100_000, 1_000_000, 2_000_000 ],
            },
            {
                name => "second",
                data => [ 100, 200, 200, 300, 300 ],
            },
            {
                name => "third",
                data => [ 2000, 2000, 2000, 2000, 2000 ],
            },
        ],
        [ 100, 300, ],
        [
            {
                name  => "first",
                iters => 100_000,
            },
            {
                name  => "second",

t/optimize-multiple-full-test.t  view on Meta::CPAN

            },
        ],
        {
            first => 1000,
        },
        'Test fractional stats due to stats_factors',
    );
}

{
    # TEST*$test_based_on_data
    test_based_on_data(
        [
            {
                name => "first",
                data => [ 50_000, 99_500, 100_000, -1, -1, ],
            },
            {
                name => "second",
                data => [ 100, 200, 200, 300, 300 ],
            },
            {
                name => "third",
                data => [ 2000, 2000, 2000, 2000, 2000 ],
            },
        ],
        [ 100, 300, ],
        [
            {
                name  => "first",
                iters => 100_000,
            },
            {
                name  => "second",



( run in 0.701 second using v1.01-cache-2.11-cpan-8d75d55dd25 )