use Benchmark qw(:all); 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 rand_box polytope. Then it counts all lattice points and takes the time # @param String ch the prefered method # (possible options: projection, latte, _4ti2, libnormaliz, bbox) # @param Int d the dimension # @param Int n number of integer points # @param Int b the upper bound for points # @param Int nmz_dual if normaliz should run in dual mode sub time_rand_box($$$$$;$) { my ($ch, $d, $n, $b, $nmz_dual, $options) = @_; my $seed = $options->{"seed"}; my $p = rand_box($d,$n,$b,{seed=>$seed}); # calculate FACETS and VERTICES before the timing starts prefer_now "ppl"; $p->FACETS; $p->VERTICES; $p->VERTICES_IN_FACETS; my $t0; my $t1; my $t; # timing if (($ch eq "libnormaliz")){ $t0=Benchmark->new; normaliz_compute($p, from_facets=>0, dual_algorithm=>$nmz_dual, degree_one_generators=>1); $t1=Benchmark->new; } else { prefer_now $ch; my $s=$p->get_schedule("N_LATTICE_POINTS"); $t0=Benchmark->new; $s->apply($p); $t1=Benchmark->new; } $t=timediff($t1,$t0); #print timestr($t)."\n"; 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 rand_box polytopes # @param Array ch the prefered method # (possible options: _4ti2, bbox, latte, libnormaliz, projection, bbox) # @param Int start_d the lower bound of the dimension # @param Int end_d the upper bound of the dimension # @param Int start_n the lower bound of the number of points # @param Int end_n the upper bound of the number of points # @option Int dimstep stepsize of the dimension # @option Int nstep stepsize of the number of points # @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_rand_box($$$$$;$) { my ($ch, $start_d, $end_d, $start_n, $end_n, $options) = @_; my $dimstep = $options->{"dimstep"}; # stepsize of the dimension my $nstep = $options->{"nstep"}; # stepsize of the right hand side 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 # upper bound for the coordinates my $b = 5; # set defaults for options if (!defined($options->{"dimstep"})) { $dimstep=1; } if (!defined($options->{"nstep"})) { $nstep=10; } 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"; } # convert $end_n to an array if (!(ref($end_n) eq "ARRAY")){ my @array=(); map { push @array, $end_n } ($start_d .. $end_d); $end_n = \@array; } # for pretty print for progress bar my $length_d = length $end_d; my $length_n = length $end_n->[0]; foreach my $chcode (@{$ch}) { my $skip = 0; my $file= "$path/rand_box_".$chcode."_$$.csv"; if(($chcode eq "libnormaliz") && ($nmz_dual == 1)){ $file= "$path/rand_box_".$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(dimension x right side) where dimension starts from '.$start_d.' to '.$end_d.' (steps are '.$dimstep.') and the number of points from '. $start_n.' to '. $end_n->[0].' (steps are '.$nstep.')"'. "\n"; print OUTPUT_FILE '"Matlab Commands: dim = '.$start_d.':'.$dimstep.':'.$end_d.' and b ='.$start_n.':'.$nstep.':'.$end_n->[0].' and mesh(points,b,import)"'."\n"; print "\n=== $chcode ===\n"; for(my $d = $start_d; $d <= $end_d; $d+=$dimstep){ for(my $n = $start_n; $n <= $end_n->[$d-$start_d]; $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->{ "$d,$n" }) ? 1: $av; progress_bar(0,$localav,(sprintf "($d,$n): $date")); for(my $i=0; $i < $localav; ++$i){ my $time = time_rand_box($chcode,$d,$n,$b,$nmz_dual,{seed=>$i}); $t += $time; $date=localtime(time); progress_bar($i+1,$localav,(sprintf "($d,$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_d}s,%${length_n}s): %9.3f -- %-80s\n", $d, $n, $t, $date; print OUTPUT_FILE $t.';'; last if($skip); } print OUTPUT_FILE "\n"; $skip = 0; } close OUTPUT_FILE; } } # computes several voronoi diagrams and takes the time. The number of points goes up by 100 # @param Array ch the prefered convex hull method (possible options: beneath_beyond, lrs, cdd) # @param Int d the dimension # @param Int n the number of random points in the cube # @param Int times the number of experiments # @option String path output path sub stats_rand_box($$$$;$) { my ($ch, $d, $n, $times, $options) = @_; # needed for pretty print for progress bar my $length_d = length $d; my $length_n = length $n; my $nmz_dual = $options->{"normaliz_dual"}; # if libnormaliz runs in dual mode # default value for the upper bound my $b = 5; # output path my $path = $options->{"path"}; if (!defined($options->{"path"})) { $path="."; } if (!defined($options->{"normaliz_dual"})) { $nmz_dual = 0; } # create output path if (!-d $path){ mkpath $path or die "can't create ouput directory: $path"; } foreach my $chcode (@{$ch}) { my $file= "$path/rand_box_stat_".$chcode."_$$.csv"; if(($chcode eq "libnormaliz") && ($nmz_dual == 1)){ $file= "$path/rand_box_stat_".$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(dimension x number) where dimension is '.$d.' and the number of points is '. $n.'. The number of experiments is '.$times.'"'. "\n"; print "\n=== $chcode ===\n"; my $date=localtime(time); progress_bar(0,$times,(sprintf "($d,$n): $date")); for(my $i = 1; $i <= $times; ++$i){ # For every set of parameters do 10 experiments and take the average my $time = time_rand_box($chcode,$d,$n,$b,$nmz_dual,{seed=>$i}); $date=localtime(time); progress_bar($i+1,$times,sprintf("($d,$n): %9.3f -- $date", $time)); print OUTPUT_FILE $time."\n"; } my $date=localtime(time); printf "(%${length_d}s,%${length_n}s): %-80s\n", $d, $n, $date; 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 ### ## 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 $path = "/path/to/store/the/output/files"; start_time_rand_box(["libnormaliz"],4,9,20,70,{ path=>$path }); start_time_rand_box(["projection"],4,9,20,70,{ path=>$path }); start_time_rand_box(["bbox"],4,9,20,[70,70,70,70,70,40],{ path=>$path }); start_time_rand_box(["latte"],4,7,20,70,{ path=>$path }); # 4ti2 and nmz dual disabled due to high variance, see below #start_time_rand_box(["_4ti2"],4,7,20,70,{ path=>$path }); #start_time_rand_box(["libnormaliz"],4,5,20,[70,30],{ path=>$path, normaliz_dual=>1 }); ## Running one example many times (100) to check standard deviation stats_rand_box(["libnormaliz","projection","bbox"],6,50,100, { path=>$path } ); stats_rand_box(["projection","bbox"],6,50,100, { path=>$path } ); stats_rand_box(["latte"],4,20,100, { path=>$path } ); ## These tests produce a high variance #stats_rand_box(["libnormaliz"],4,20,100, { path=>$path, normaliz_dual=>1 } ); ## Setting a ulimit on time aborts the extreme cases after one hour # ulimit -t 3600 #stats_rand_box(["_4ti2"],4,20,100, { path=>$path } );