Algorithm-Knap01DP

 view release on metacpan or  search on metacpan

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

package Algorithm::Knap01DP;
use 5.008004;
use strict;
use warnings;
use Carp;
use IO::File;

our $VERSION = '0.25'; 
# Still a very early "alpha" version

sub new {
    my $class = shift;
    my $self = {
        capacity    => 0,       # total capacity of this knapsack
        numobjects  => 0,       # number of objects
        weights     => [],      # weights to be packed into the knapsack
        profits     => [],      # profits to be packed into the knapsack
        tableval    => [],      # f[k][c] DP table of values
        tablesol    => [],      # x[k][c] DP table of sols 
                                # (0 = out, 1 = in, 2 = in and out)
        solutions   => [],      # list of lists of object indexes 
        filename    => "",      # name of the file the problem was read from
        @_,
    };
    
    croak "Profits and Weights don't have the same size" 
           unless scalar(@{$self->{weights}}) == scalar(@{$self->{profits}});

    bless $self, $class;
}

sub Knap01DP {
  my $self = shift();
  my $M = $self->{capacity};
  my @w = @{$self->{weights}};
  my @p = @{$self->{profits}};

  croak "Weight list is empty" unless (@w > 0);

  my $N = @w;
  my (@f, @x);

  for my $c (0..$M) {
    if ($w[0] <= $c) {
      $f[0][$c] = $p[0];
      $x[0][$c] = 1;
    }
    else {
      $f[0][$c] = 0;
      $x[0][$c] = 0;
    }
  }

  for my $k (1..$N-1) {
    for my $c (0..$M) {
      my $n = $f[$k-1][$c];
      if ($c >= $w[$k]) {
        my $y = $f[$k-1][$c-$w[$k]]+$p[$k];
        if ($n < $y) {
          $f[$k][$c] = $y;
          $x[$k][$c] = 1;
        }
        elsif ($n > $y) { 
          $f[$k][$c] = $n;
          $x[$k][$c] = 0;
        }
        else { # $n == $y
          $f[$k][$c] = $n;
          $x[$k][$c] = 2; # both ways
        }
      }
      else { 
        $f[$k][$c] = $n; 
        $x[$k][$c] = 0; 
      }
    }
  }
  ($self->{tableval}, $self->{tablesol}) = (\@f, \@x);
}

sub solutions {
  my $self = shift();
  my $N = $self->{numobjects};
  my $M = $self->{capacity};
  my @w = @{$self->{weights}};
  my (@f, @x);

  $self->Knap01DP() if (!@{$self->{tableval}});
  @f = @{$self->{tableval}}; 



( run in 1.337 second using v1.01-cache-2.11-cpan-5b529ec07f3 )