use Benchmark qw(:all); use application 'polytope'; #------------------------------------ # Convex hull computations with # lrs, cdd, beneath_beyond #------------------------------------ # Measures the time for computing the convex hull of the # cut polytope with respect to a given graph //g// with # the convex hull code //ch//. # @param String ch the convex hull code # @param Graph g the graph from which the cut polytope is constructed # @return TIME_OBJECT the computation time sub time_cut_poly { my ($ch, $g) = @_; my $c = cut_polytope($g->ADJACENCY); my $t; prefer_now $ch; my $t0=Benchmark->new; $c->FACETS; my $t1=Benchmark->new; $t=timediff($t1,$t0); return $t; } # Records the average time (in //n_runs// runs) for computing the # convex hull of the cut polytope of a path with //n_nodes// nodes # with the convex hull codes lrs, cdd, and beneath_beyond. # The result is stored in a file. The path to the file can be # specified in //fpath// (e.g. "/tmp"). # @param Int n_nodes the number of nodes of the path # @param Int n_runs the number of runs # @param $fpath the path to the file sub time_path { my ($n_nodes, $n_runs, $fpath) = @_; my $date = localtime(time); my $g = path_graph($n_nodes); my $file = $fpath."/cut_poly_path_".$n_nodes."_nodes_".$n_runs."_runs.log"; # Open output file open OUTPUT_FILE, ">$file" or die "can't create outputfile $file: $!"; print(OUTPUT_FILE "Date: $date\n"); print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Cut polytope of a path with ".$n_nodes." nodes:\n----------------------------------------------------\n"); foreach my $ch ("ppl","lrs","cdd","beneath_beyond") { #foreach my $ch ("ppl") { print(OUTPUT_FILE "\n=== $ch ===\n----------------------------------------------------\n"); print "\n=== $ch ===\n"; my $s=0; foreach (0..$n_runs-1) { my $t = time_cut_poly($ch,$g);print timestr($t); print(OUTPUT_FILE "Run ".($_+1).": ".timestr($t)."\n"); print timestr($t)."\n"; $s += $t->[1]; } print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Time on average ($ch, $n_runs runs, path with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"); print "\nTime on average ($ch, $n_runs runs, path with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"; } close OUTPUT_FILE; } # See subroutine time_path. sub time_cycle { my ($n_nodes, $n_runs, $fpath) = @_; my $date = localtime(time); my $g = cycle_graph($n_nodes); my $file = $fpath."/cut_poly_cycle_".$n_nodes."_nodes_".$n_runs."_runs.log"; # Open output file open OUTPUT_FILE, ">$file" or die "can't create outputfile $file: $!"; print(OUTPUT_FILE "Date: $date\n"); print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Cut polytope of a cycle with ".$n_nodes." nodes:\n----------------------------------------------------\n"); foreach my $ch ("ppl","lrs","cdd","beneath_beyond") { #foreach my $ch ("ppl") { print(OUTPUT_FILE "\n=== $ch ===\n----------------------------------------------------\n"); print "\n=== $ch ===\n"; my $s=0; foreach (0..$n_runs-1) { my $t = time_cut_poly($ch,$g);print timestr($t); print(OUTPUT_FILE "Run ".($_+1).": ".timestr($t)."\n"); print timestr($t)."\n"; $s += $t->[1]; } print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Time on average ($ch, $n_runs runs, cycle with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"); print "\nTime on average ($ch, $n_runs runs, cycle with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"; } close OUTPUT_FILE; } # See subroutine time_path. sub time_Kn { my ($n_nodes, $n_runs, $fpath) = @_; my $date = localtime(time); my $g = complete($n_nodes); my $file = $fpath."/cut_poly_complete_".$n_nodes."_nodes_".$n_runs."_runs.log"; # Open output file open OUTPUT_FILE, ">$file" or die "can't create outputfile $file: $!"; print(OUTPUT_FILE "Date: $date\n"); print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Cut polytope of the complete graph with ".$n_nodes." nodes:\n----------------------------------------------------\n"); foreach my $ch ("ppl","lrs","cdd","beneath_beyond") { # foreach my $ch ("lrs","cdd") { # foreach my $ch ("ppl") { if($n_nodes != 7 || $ch ne "beneath_beyond"){ print(OUTPUT_FILE "\n=== $ch ===\n----------------------------------------------------\n"); print "\n=== $ch ===\n"; my $s=0; foreach (0..$n_runs-1) { my $t = time_cut_poly($ch,$g);print timestr($t); print(OUTPUT_FILE "Run ".($_+1).": ".timestr($t)."\n"); print timestr($t)."\n"; $s += $t->[1]; } print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Time on average ($ch, $n_runs runs, complete graph with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"); print "\nTime on average ($ch, $n_runs runs, complete graph with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"; } } close OUTPUT_FILE; } #------------------------------------ # Computations up to symmetry #------------------------------------ # Measures the time for computing the convex hull up to symmetry # of the cut polytope with respect to a given graph //g// # (hopefully some day with the convex hull code //ch//). # @param String ch the convex hull code # @param Graph g the graph from which the cut polytope is constructed # @param GroupOfPolytope group the given subgroup of the linear symmetry group of the cut polytope # @return TIME_OBJECT the computation time sub time_cut_poly_sym { my ($ch, $g, $group) = @_; my $c = cut_polytope($g->ADJACENCY); $c->GROUP = new group::GroupOfPolytope($group); my $t; my $rayCompMethod; if ($ch eq "lrs") { $rayCompMethod = 0; } elsif ($ch eq "cdd") { $rayCompMethod = 1; } elsif ($ch eq "beneath_beyond") { $rayCompMethod = 2; } elsif ($ch eq "ppl") { $rayCompMethod = 3; } else { die "time_cut_poly_sym: wrong specifier for convex hull code; only lrs, cdd, or beneath_beyond are available" } my $t0=Benchmark->new; my ($success, $ineq, $eq) = representation_conversion_up_to_symmetry($c, $c->GROUP, 1, $rayCompMethod); my $t1=Benchmark->new; if (!$success) { croak("internal sympol error"); } $t=timediff($t1,$t0); return $t; } # Records the average time (in //n_runs// runs) for computing the # convex hull up to symmetry of the cut polytope of a path with # //n_nodes// nodes (goal: with sympol+lrs, sympol+cdd). # The result is stored in a file. The path to the file can be # specified in //fpath// (e.g. "/tmp"). # @param Int n_nodes the number of nodes of the path # @param Int n_runs the number of runs # @param Bool choose_induced_syms (1) use the symmetries induced by graph symmetries # or (0) the full linear symmetry group of the corresponding cut polytope # @param $fpath the path to the file sub time_path_sym { my ($n_nodes, $n_runs, $choose_induced_syms, $fpath) = @_; my $date = localtime(time); my $g = path_graph($n_nodes); my $group; my $file; my $c = cut_polytope($g->ADJACENCY); # for sym group computation if ($choose_induced_syms == 1) { my $I = new IncidenceMatrix($g->EDGES); my $pairs_of_gens = automorphisms($I); my @edge_gens = map {$_->first} @$pairs_of_gens; # The action on the edges of the graph induces an action on the coordinates of the cut polytope. my $group_on_edges = new group::GroupOfPolytope( GENERATORS=>(new Array< Array >(\@edge_gens)), DOMAIN=>$polytope::domain_OnCoords ); $group = convert_coord_action($group_on_edges, $c->VERTICES, $polytope::domain_OnRays); $file = $fpath."/induced_sym_cut_poly_path_".$n_nodes."_nodes_".$n_runs."_runs.log"; } else { $group = linear_symmetries($c,1); $file = $fpath."/sym_cut_poly_path_".$n_nodes."_nodes_".$n_runs."_runs.log"; } # Open output file open OUTPUT_FILE, ">$file" or die "can't create outputfile $file: $!"; print(OUTPUT_FILE "Date: $date\n"); print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Cut polytope up to symmetry of a path with ".$n_nodes." nodes:\n----------------------------------------------------\n"); foreach my $ch ("ppl","lrs","cdd","beneath_beyond") { # foreach my $ch ("cdd") { print(OUTPUT_FILE "\n=== $ch ===\n----------------------------------------------------\n"); print "\n=== sym $ch ===\n"; my $s=0; foreach (0..$n_runs-1) { my $t = time_cut_poly_sym($ch,$g,$group);print timestr($t); print(OUTPUT_FILE "Run ".($_+1).": ".timestr($t)."\n"); print timestr($t)."\n"; $s += $t->[1]; } print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Time on average (sym $ch, $n_runs runs, path with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"); print "\nTime on average (sym $ch, $n_runs runs, path with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"; } close OUTPUT_FILE; } # See subroutine time_path_sym. sub time_cycle_sym { my ($n_nodes, $n_runs, $choose_induced_syms, $fpath) = @_; my $date = localtime(time); my $g = cycle_graph($n_nodes); my $group; my $file; my $c = cut_polytope($g->ADJACENCY); # for sym group computation if ($choose_induced_syms == 1) { my $I = new IncidenceMatrix($g->EDGES); my $pairs_of_gens = automorphisms($I); my @edge_gens = map {$_->first} @$pairs_of_gens; # The action on the edges of the graph induces an action on the coordinates of the cut polytope. my $group_on_edges = new group::GroupOfPolytope( GENERATORS=>(new Array< Array >(\@edge_gens)), DOMAIN=>$polytope::domain_OnCoords ); $group = convert_coord_action($group_on_edges, $c->VERTICES, $polytope::domain_OnRays); $file = $fpath."/induced_sym_cut_poly_cycle_".$n_nodes."_nodes_".$n_runs."_runs.log"; } else { $group = linear_symmetries($c,1); $file = $fpath."/sym_cut_poly_cycle_".$n_nodes."_nodes_".$n_runs."_runs.log"; } # Open output file open OUTPUT_FILE, ">$file" or die "can't create outputfile $file: $!"; print(OUTPUT_FILE "Date: $date\n"); print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Cut polytope up to symmetry of a cycle with ".$n_nodes." nodes:\n----------------------------------------------------\n"); foreach my $ch ("ppl","lrs","cdd","beneath_beyond") { # foreach my $ch ("cdd") { print(OUTPUT_FILE "\n=== $ch ===\n----------------------------------------------------\n"); print "\n=== sym $ch ===\n"; my $s=0; foreach (0..$n_runs-1) { my $t = time_cut_poly_sym($ch,$g,$group);print timestr($t); print(OUTPUT_FILE "Run ".($_+1).": ".timestr($t)."\n"); print timestr($t)."\n"; $s += $t->[1]; } print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Time on average (sym $ch, $n_runs runs, cycle with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"); print "\nTime on average (sym $ch, $n_runs runs, cycle with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"; } close OUTPUT_FILE; } # See subroutine time_path_sym. sub time_Kn_sym { my ($n_nodes, $n_runs, $choose_induced_syms, $fpath) = @_; my $date = localtime(time); my $g = complete($n_nodes); my $group; my $file; my $c = cut_polytope($g->ADJACENCY); # for sym group computation if ($choose_induced_syms == 1) { my $I = new IncidenceMatrix($g->EDGES); my $pairs_of_gens = automorphisms($I); my @edge_gens = map {$_->first} @$pairs_of_gens; # The action on the edges of the graph induces an action on the coordinates of the cut polytope. my $group_on_edges = new group::GroupOfPolytope( GENERATORS=>(new Array< Array >(\@edge_gens)), DOMAIN=>$polytope::domain_OnCoords ); $group = convert_coord_action($group_on_edges, $c->VERTICES, $polytope::domain_OnRays); $file = $fpath."/induced_sym_cut_poly_complete_".$n_nodes."_nodes_".$n_runs."_runs.log"; } else { $group = linear_symmetries($c,1); $file = $fpath."/sym_cut_poly_complete_".$n_nodes."_nodes_".$n_runs."_runs.log"; } # Open output file open OUTPUT_FILE, ">$file" or die "can't create outputfile $file: $!"; print(OUTPUT_FILE "Date: $date\n"); print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Cut polytope up to symmetry of the complete graph with ".$n_nodes." nodes:\n----------------------------------------------------\n"); foreach my $ch ("ppl","lrs","cdd","beneath_beyond") { # foreach my $ch ("cdd") { if($n_nodes != 7 || $ch ne "beneath_beyond"){ print(OUTPUT_FILE "\n=== $ch ===\n----------------------------------------------------\n"); print "\n=== sym $ch ===\n"; my $s=0; foreach (0..$n_runs-1) { my $t = time_cut_poly_sym($ch,$g,$group);print timestr($t); print(OUTPUT_FILE "Run ".($_+1).": ".timestr($t)."\n"); print timestr($t)."\n"; $s += $t->[1]; } print(OUTPUT_FILE "----------------------------------------------------\n"); print(OUTPUT_FILE "Time on average (sym $ch, $n_runs runs, complete graph with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"); print "\nTime on average (sym $ch, $n_runs runs, complete graph with $n_nodes nodes): ". ($s*1000/$n_runs) . " milliseconds.\n\n"; } } close OUTPUT_FILE; } ## If you want to trigger the run commands automatically just remove the next line return; #------------------------------------ # Function calls #------------------------------------ my $n_runs = 10; my $choose_induced_syms = 1; # uses induced symmetries of graph instead of linear symmetries of cut polytope (set to 0 for linear symmetries!) my $path = "/path/to/store/the/output/files"; foreach my $n_nodes (9,10) { time_path($n_nodes,$n_runs,$path); time_cycle($n_nodes,$n_runs,$path); time_path_sym($n_nodes,$n_runs,$choose_induced_syms,$path); time_cycle_sym($n_nodes,$n_runs,$choose_induced_syms,$path); } time_Kn(6,$n_runs,$path); time_Kn_sym(6,$n_runs,$choose_induced_syms,$path); time_Kn(7,1,$path); time_Kn_sym(7,$n_runs,$choose_induced_syms,$path);