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 # @param Int nmz_dual if normaliz should run in dual mode sub time_matching_polytope($$$) { my ($ch, $n, $nmz_dual) = @_; # initializing start graph my $g=complete($n)->ADJACENCY; my $P=matching_polytope($g); my $t; # helping the scheduler #prefer_now "ppl"; $P->POINTED; $P->FACETS; if (($ch eq "projection")){ prefer_now "ppl"; $P->VERTICES; } my $t0; my $t1; if (($ch eq "libnormaliz")){ $P->MONOID_GRADING; $t0=Benchmark->new; normaliz_compute($P, from_facets=>1, dual_algorithm=>$nmz_dual, degree_one_generators=>1); $t1=Benchmark->new; } else { my $target = ($ch eq "azove") ? "N_01POINTS" : "N_LATTICE_POINTS"; prefer_now $ch; my $s=$P->get_schedule("$target"); $t0=Benchmark->new; my $ret=$s->apply($P); $t1=Benchmark->new; } $t=timediff($t1,$t0); if (($ch eq "projection") || ($ch eq "bbox") || ($ch eq "libnormaliz")){ return $t->cpu_p; } else { # measure child process only return $t->cpu_c; } } # 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_matching_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 my $nmz_dual = $options->{"normaliz_dual"}; # if libnormaliz runs in dual mode # 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; } if (!defined($options->{"normaliz_dual"})) { $nmz_dual = 0; } # 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/matching_".$chcode."_$$.csv"; if(($chcode eq "libnormaliz") && ($nmz_dual == 1)){ $file= "$path/matching_".$chcode."_dual_$$.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_matching_polytope($chcode,$n, $nmz_dual); $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; 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; ### ## To use only one thread for normaliz set the following environment variable # export OMP_NUM_THREADS=1 $path = "/path/to/store/the/output/files"; start_time_matching_polytope(["azove"],4,19, { path=>$path }); start_time_matching_polytope(["_4ti2"],4,9, { path=>$path }); start_time_matching_polytope(["bbox"],4,7, { path=>$path }); start_time_matching_polytope(["projection"],4,9, { path=>$path }); start_time_matching_polytope(["libnormaliz"],4,7, { path=>$path }); start_time_matching_polytope(["libnormaliz"],4,10, { path=>$path, normaliz_dual=>1 }); ### ## to run latte in all primal mode use the polymake command # set_custom($latte_count_param="--irrational-all-primal --maxdet=25 --exponential"); ## and restart polymake start_time_matching_polytope(["latte"],4,7, { path=>$path }); # default #start_time_matching_polytope(["latte"],4,5, { path=>$path }); # all primal