AI-Pathfinding-OptimizeMultiple

 view release on metacpan or  search on metacpan

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

    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() }

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

    $self->chosen_scans( [] );

    $self->_total_boards_solved(0);
    $self->_total_iters(0);

    $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() );

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

    return;
}

sub _selected_scans
{
    my $self = shift;

    return $self->_input_obj->selected_scans();
}

sub _map_all_but_last
{
    my $self = shift;

    my ( $cb, $arr_ref ) = (@_);

    return [
        ( map { $cb->($_) } @$arr_ref[ 0 .. $#$arr_ref - 1 ] ),
        $arr_ref->[-1]
    ];
}

sub _get_quotas
{
    my $self = shift;
    if ( $self->_quotas_are_cb() )
    {
        return scalar( eval( $self->_quotas_expr() ) );

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

sub _get_line_of_command
{
    my $self = shift;

    my $args_string = join( " ",
        $self->_start_board(),
        $self->_start_board() + $self->_num_boards() - 1, 1 );
    return "freecell-solver-range-parallel-solve $args_string";
}

sub _line_ends_mapping
{
    my $self = shift;
    return $self->_map_all_but_last( sub { "$_[0] \\\n" }, shift );
}

sub _get_used_scans
{
    my $self = shift;
    return [ grep { $_->is_used() } @{ $self->_selected_scans() } ];
}

sub _get_scan_line
{
    my ( $self, $line ) = @_;

    return
          $line->{'cmd_line'}
        . " -step 500 "
        . join( " ",
        map { $_, $line->{'id'} }
            ( "--st-name", ( $self->_is_flares() ? "--flare-name" : () ) ) );
}

sub _get_lines_of_scan_defs
{
    my $self = shift;
    return [ map { $self->_get_scan_line($_) } @{ $self->_get_used_scans() } ];
}

sub _scan_def_line_mapping
{
    my ( $self, $lines_aref ) = @_;

    return $self->_map_all_but_last(
        sub {
            my ($line) = @_;

            return $line . ' ' . ( $self->_is_flares() ? "-nf" : "-nst" );
        },
        [
            map {
                my $line = $_;

                # Add the -sp r:tf flag to each scan if specified - it enhances
                # performance, but timing the scans with it makes the total
                # scan sub-optimal.
                if ( $self->_add_horne_prune() )
                {
                    $line =~ s/( --st-name)/ -sp r:tf$1/;
                }
                $line;

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

    if ( $self->_offset_quotas() )
    {
        return $quota + 1;
    }
    else
    {
        return $quota;
    }
}

sub _map_scan_idx_to_id
{
    my $self  = shift;
    my $index = shift;

    return $self->_selected_scans()->[$index]->id();
}

sub _format_prelude_iter
{
    my $self = shift;

    my $iter = shift;

    return
          ( $self->_is_flares() ? "Run:" : "" )
        . $iter->iters() . '@'
        . $self->_map_scan_idx_to_id( $iter->scan_idx() );
}

sub _get_line_of_prelude
{
    my $self = shift;
    return
        +( $self->_is_flares() ? "--flares-plan" : "--prelude" ) . qq{ "}
        . join( ",",
        map { $self->_format_prelude_iter($_) } @{ $self->_chosen_scans() } )
        . "\"";
}

sub _calc_script_lines
{
    my $self = shift;
    return [
        $self->_get_line_of_command(),
        @{
            $self->_scan_def_line_mapping( $self->_get_lines_of_scan_defs() )
        },
        $self->_get_line_of_prelude()
    ];
}

sub _calc_script_text
{
    my $self = shift;
    return join( "",
        @{ $self->_line_ends_mapping( $self->_calc_script_lines() ) } );
}

sub _write_script
{
    my $self = shift;

    $self->_out_script( $self->_calc_script_text() );
}

sub _calc_scans_iters_pdls

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

}

sub _init_arbitrator
{
    my $self = shift;

    return $self->_arbitrator(
        AI::Pathfinding::OptimizeMultiple->new(
            {
                'scans' => [
                    map { +{ name => $_->id() } }
                        @{ $self->_input_obj->_suitable_scans_list() },
                ],
                'quotas'           => $self->_get_quotas(),
                'selected_scans'   => $self->_selected_scans(),
                'num_boards'       => $self->_num_boards(),
                'scans_iters_pdls' => $self->_calc_scans_iters_pdls(),
                'trace_cb'         => \&_arbitrator_trace_cb,
                'optimize_for'     => $self->_optimize_for(),
                'stats_factors'    => $self->_stats_factors(),
            }

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

    }
}

sub _get_run_string
{
    my $self    = shift;
    my $results = shift;

    return join(
        "",
        map {
            sprintf( '%i@%i,',
                $_->iters(), $self->_map_scan_idx_to_id( $_->scan_idx() ) )
        } @{ $self->_post_processor->process( $results->scan_runs() ) },
    );
}

sub _do_simulation_for_board
{
    my ( $self, $board ) = @_;

    my $results = $self->_arbitrator()->simulate_board($board);

    my $scan_mapper = sub {
        my $index = shift;

        return $self->_map_scan_idx_to_id($index);
    };

    return sprintf( "%i:%s:%s:%i",
        $board + 1,
        $results->get_status(),
        $self->_get_run_string($results),
        $results->get_total_iters(),
    );
}

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

);

has _scan_ids_to_indexes => (
    isa     => 'HashRef[Int]',
    is      => 'ro',
    lazy    => 1,
    default => sub {
        my ($self) = @_;

        my $scan_ids = $self->get_scan_ids_aref;
        return +{ map { $scan_ids->[$_] => $_ } 0 .. $#$scan_ids };
    },
);

sub _slurp
{
    my $filename = shift;

    open my $in, "<", $filename
        or die "Could not open $filename";

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

{
    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 (

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

    }
    close($from_cmd);
    close($fcs_out);
    close($fc_pro_out);
}

sub get_scan_ids_aref
{
    my $self = shift;

    return [ map { $_->id() } @{ $self->selected_scans } ];
}

sub lookup_scan_idx_based_on_id
{
    my ( $self, $scan_id ) = @_;

    my $idx = $self->_scan_ids_to_indexes->{$scan_id};
    if ( !defined($idx) )
    {
        die "Index '$idx' does not exist!";

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

=head2 $self->get_next_id()

Retrieves the next scan ID and increment it.

=head2 $self->get_prev_scans()

Returns an array reference of previous scan hash-refs.

=head2 my $hash_ref = $self->get_scans_iters_pdls()

Returns the hash ref mapping scan IDs/names to iteration PDLs.

=head2 my $hash_ref = $self->get_scans_lens_iters_pdls()

Returns the hash ref mapping scan IDs/names to iteration+lengths PDLs.

=head2 $self->num_boards()

The number of boards.

=head2 $self->selected_scans()

An accessor for the selected scans.

=head2 $self->start_board()

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

    return \@a;
}

sub process
{
    my $self = shift;

    my $scans_orig = shift;

    # clone the scans.
    my $scans = [ map { $_->clone(); } @{$scans_orig} ];

    if ( $self->_offset_quotas )
    {
        $scans = [
            map {
                my $ret = $_->clone();
                $ret->iters( $ret->iters() + 1 );
                $ret;
            } @$scans
        ];
    }

    if ( $self->_should_do_rle )
    {
        $scans = $self->scans_rle($scans);

t/00-compile.t  view on Meta::CPAN

use IO::Handle;

open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!";

my @warnings;
for my $lib (@module_files)
{
    # see L<perlfaq8/How can I capture STDERR from an external command?>
    my $stderr = IO::Handle->new;

    diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} }
            $^X, @switches, '-e', "require q[$lib]"))
        if $ENV{PERL_COMPILE_TEST_DEBUG};

    my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]");
    binmode $stderr, ':crlf' if $^O eq 'MSWin32';
    my @_warnings = <$stderr>;
    waitpid($pid, 0);
    is($?, 0, "$lib loaded ok");

    shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/

t/00-compile.t  view on Meta::CPAN

    my $line = <$fh>;

    close $fh and skip("$file isn't perl", 1) unless $line =~ /^#!\s*(?:\S*perl\S*)((?:\s+-\w*)*)(?:\s*#.*)?$/;
    @switches = (@switches, split(' ', $1)) if $1;

    close $fh and skip("$file uses -T; not testable with PERL5LIB", 1)
        if grep { $_ eq '-T' } @switches and $ENV{PERL5LIB};

    my $stderr = IO::Handle->new;

    diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} }
            $^X, @switches, '-c', $file))
        if $ENV{PERL_COMPILE_TEST_DEBUG};

    my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-c', $file);
    binmode $stderr, ':crlf' if $^O eq 'MSWin32';
    my @_warnings = <$stderr>;
    waitpid($pid, 0);
    is($?, 0, "$file compiled ok");

    shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/

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

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 = (
        map {
            +{
                name  => $scans_aref->[ $_->scan_idx ]->{name},
                iters => $_->iters,
            }
        } @{ $obj->chosen_scans() }
    );

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



( run in 0.585 second using v1.01-cache-2.11-cpan-49f99fa48dc )