use Benchmark qw(:all); use Benchmark ':hireswallclock'; use File::Path qw(mkpath); use application 'polytope'; # prints a progressbar # @param Int got : the amount of stuff you have already got # @param Int total : the total amount of stuff # @param String text : additional text behind the bar. sub progress_bar { my ( $got, $total, $text) = @_; my $width = 10; my $char = '='; local $| = 1; printf "|%-${width}s| $got/$total | %-80s \r", $char x (($width)*$got/$total). '>', $text; } # creates a certain knapsack polytope, where the coordinates from the normal vector # are the fibonacci sequence. Then it counts all lattice points and takes the time # @param String ch the prefered method # (possible options: cdd, lrs, beneath_beyond, libnormaliz) # @param Int n length of the path at the end sub time_cut_polytope($$) { my ($ch, $n) = @_; # initializing start graph my $g=new props::Graph($n+6); $g->edge(0,1); $g->edge(1,2); $g->edge(1,4); $g->edge(2,3); $g->edge(3,4); $g->edge(4,5); for (my $i=0; $i < $n; ++$i) { $g->edge(5+$i,6+$i); } my $P=cut_polytope($g); my $t; # helping the scheduler $P->POINTED; prefer_now $ch; my $s=$P->get_schedule("FACETS"); my $t0; my $t1; if ($ch eq "libnormaliz"){ # code calling nmz directly: $t0=Benchmark->new; normaliz_compute($P,from_facets=>0,facets=>1,verbose=>0,skip_long=>0); $t1=Benchmark->new; # code calling nmz via the rules: (does not make a difference since the schedule is precomputed earlier) #$t0=Benchmark->new; $s->apply($P); $t1=Benchmark->new; }else{ $t0=Benchmark->new; $s->apply($P); $t1=Benchmark->new; } $t=timediff($t1,$t0); # return wallclock instead because of the multithreaded tests for normaliz return $t->real; } # counts lattice points from several fibonacci knapsack polytopes # @param Array ch the prefered method # (possible options: cdd, lrs, beneath_beyond, libnormaliz) # @param Int start_n the lower bound of the path length # @param Int end_n the upper bound of the path length # @option Int nstep stepsize of the path length # @option Int av number of experiments for one parameter set # @option String path output path # @option Hash only_once parameters that should run only once # @option Int time_limit maximum time (+10%) to skip following tests sub start_time_cut_polytope($$$;$) { my ($ch, $start_n, $end_n, $options) = @_; my $nstep = $options->{"nstep"}; # stepsize of the path length my $av = $options->{"av"}; # number of experiements with the same parameterset my $path = $options->{"path"}; # output path my $only_once = $options->{"only_once"}; # which parameters should run only once my $time_limit = $options->{"time_limit"}; # time limit # set defaults for options if (!defined($options->{"nstep"})) { $nstep=1; } if (!defined($options->{"av"})) { $av=10; } if (!defined($options->{"path"})) { $path="."; } if (!defined($options->{"only_once"})) { $only_once = {}; } if (!defined($options->{"time_limit"})) { $time_limit = 3600; } # create output path if (!-d $path){ mkpath $path or die "can't create ouput directory: $path"; } # for pretty print for progress bar my $length_n = length $end_n; foreach my $chcode (@{$ch}) { my $skip = 0; my $file= "$path/ns_cut_".$chcode.".csv"; # Open output file open OUTPUT_FILE, ">$file" or die "can't create outputfile $file: $!"; $|=1; OUTPUT_FILE->autoflush(1); print OUTPUT_FILE '"time(path length) where the path length starts from '.$start_n.' to '.$end_n.' (steps are '.$nstep.')"'. "\n"; print OUTPUT_FILE '"Matlab Commands: n = '.$start_n.':'.$nstep.':'.$end_n.' and plot(points,n,import)"'."\n"; print "\n=== $chcode ===\n"; # first time without timing. Just to make sure no recompiling comes in the way #time_knapsack($chcode,$start_d,$start_b,$first,$second); for(my $n = $start_n; $n <= $end_n; $n+=$nstep){ # For every set of parameters do $av experiments and take the average my $t = 0; my $date=localtime(time); my $localav = exists($only_once->{ "$n" }) ? 1: $av; progress_bar(0,$localav,"($n): $date"); for(my $i=0; $i < $localav; ++$i){ my $time = time_cut_polytope($chcode,$n); $t += $time; $date=localtime(time); progress_bar($i+1,$localav,(sprintf "($n): %9.3f -- $date", $time)); if($time > 1.1*$time_limit){ $skip=1; $localav = $i+1; # for correct av. last; } } $t = sprintf "%.3f", $t/$localav; my $date=localtime(time); printf "(%${length_n}s): %9.3f -- %-80s\n", $n, $t, $date; print OUTPUT_FILE $t.';'; print OUTPUT_FILE "\n"; last if($skip); } close OUTPUT_FILE; } } ## If you want to trigger the run commands automatically just remove the next line return; my $path = "/path/to/store/the/output/files"; start_time_cut_polytope(["porta"],0,7, { path=>$path }); start_time_cut_polytope(["beneath_beyond"],0,4, { path=>$path, }); start_time_cut_polytope(["cdd"],0,9, { path=>$path }); start_time_cut_polytope(["lrs"],0,5, { path=>$path, only_once=>{"5"=>1 } }); start_time_cut_polytope(["ppl"],0,14, { path=>$path }); ### ## If you want to use only one thread for normaliz set the following environment variable ## export OMP_NUM_THREADS=1 #start_time_cut_polytope(["libnormaliz"],0,14, { path=>$path, only_once=>{"14"=>1 } }); ### ## If you want to use more than one thread for normaliz set the following environment variable ## export OMP_NUM_THREADS=6 #start_time_cut_polytope(["libnormaliz"],0,14, { path=>$path, only_once=>{"14"=>1 } });