def benchmark(mst_binary, input_graph, out, rev, trial_num, for_time): rel_input_graph = ppinput(input_graph) if not print_benchmark(rel_input_graph, out, rev, trial_num, for_time): trial_num = -1 # cancel logging # determine how to save the output kill_out = False if for_time or out != '/dev/null': # disable /dev/null for performance experiments so we can get the weight for now ... if out == '/dev/null': out = random_tmp_filename(10, 'weight-for-time') kill_out = True save_cmd = '> ' + out else: # save just the first line of output so we can get the weight out = random_tmp_filename(10, 'weight') save_cmd = '| head -n 1 > ' + out kill_out = True # run mst (and time it) time_file = random_tmp_filename(10, 'time') cmd = '/usr/bin/time -f %%U -o %s %s %s %s' % (time_file, mst_binary, input_graph, save_cmd) ret = os.system(cmd) if ret != 0: print >> sys.stderr, "mst exited with error: " + cmd quiet_remove(time_file) return try: time_sec = extract_answer(time_file) except CheckerError, e: print >> sys.stderr, "failed to read time file: " + str(e) return
def __compute_mst_weight(input_graph, corr_file): """Internal method to actual compute the MST weight of input_graph""" checker = get_path_to_checker_binary(True) ret = os.system('%s %s > %s' % (checker, input_graph, corr_file)) if ret == 0: return extract_answer(corr_file) else: raise CheckerError("checker error: failed to generate output for " + ppinput(input_graph))
def __get_ti(input_graph): try: return extract_input_footer(input_graph) except ExtractInputFooterError, e: raise CheckerError("checker error: unable to extract the input footer for %s: %s" % (ppinput(input_graph), e))
outcome = INCORRECT if ans_out is not None: (ti, ans_corr) = get_and_log_mst_weight_from_checker(input_graph, force_recompute, inputslogfn) else: ti = None # are they the same? if ans_out is not None: fmt = '%.' + str(tolerance) + 'f' str_ans_corr = fmt % ans_corr str_ans_out = fmt % ans_out if str_ans_corr == str_ans_out: outcome = CORRECT else: print >> sys.stderr, "correctness FAILED: %s (correct is %s, output had %s)" % (ppinput(input_graph), str_ans_corr, str_ans_out) outcome = INCORRECT # log the result of the correctness check if rev is not None and run is not None: if ti is None: ti = __get_ti(input_graph) data = CorrResult(ti.dims, ti.min, ti.max, ti.num_verts, ti.num_edges, ti.seed, rev, run, outcome) try: DataSet.add_data_to_log_file(data) print 'logged correctness result to ' + data.get_path() except DataError, e: fmt = "Unable to log result to file %s (correct is %s, output had %s): %s" print >> sys.stderr, fmt % (ppinput(input_graph), str_ans_corr, str_ans_out, e)
def main(argv=sys.argv[1:], get_output_name_only=False, get_is_for_part2=False): usage = """usage: %prog [options] NUM_VERTICES Generates a connected graph with no self-loops or parallel edges. Output is sent to the default filename (""" + get_path_to_generated_inputs() + """/with V-E-SEED.g unless -e or -v are specified in which case a random filename is used.)""" parser = OptionParser(usage) parser.add_option("-c", "--correctness", action="store_true", default=False, help="compute and log the correct output") parser.add_option( "-d", "--dont-generate", action="store_true", default=False, help="add the input to the inputs list file but do not generate it") parser.add_option( "-l", "--inputs-list-file", metavar="FILE", help= "set the file to store info about the new input to (default is usually fine)" ) parser.add_option( "-m", "--may-use-existing", action="store_true", default=False, help="will not generate a new graph if the output file already exists") parser.add_option( "-n", "--num-edges", help="number of edges to put in the graph [default: complete graph]") parser.add_option( "-o", "--output-file", help= "where to output the generated graph [default is inputs/[<STYLE>-]<NUM_VERTICES>-<NUM_EDGES>-<RANDOM_SEED>.g" ) parser.add_option( "-p", "--precision", type="int", default=1, help= "number of decimal points to specify for edge weights [default: %default]" ) parser.add_option("-q", "--quiet", action="store_true", default=False, help="do not log any extraneous information to stdout") parser.add_option( "-r", "--random-seed", metavar="R", type="int", default=None, help= "what random seed to use [default: choose a truly random seed using urandom()]" ) parser.add_option( "-s", "--style", help= "how to place edges [default: random with no self-loops or parallel edges]" ) parser.add_option( "-t", "--dont-track", action="store_true", default=False, help="whether to log this input in our list of generated inputs") group = OptionGroup(parser, "Generation Type Options") group.add_option( "-e", "--edge-weight-range", metavar="MIN,MAX", help="range of edge weights (range inclusive) [default: [0.1,100000]]") group.add_option( "-v", "--vertex-pos-range", metavar="DIM,MIN,MAX", help= "dimensionality of vertex positions and the range of each dimension (range inclusive) [not used by default; mutually exclusive with -e]" ) parser.add_option_group(group) (options, args) = parser.parse_args(argv) if len(args) < 1: parser.error("missing NUM_VERTICES") elif len(args) > 1: parser.error("too many arguments") # make sure --dont-generate isn't specified along with mutex switches if options.dont_generate: if options.correctness: parser.error('-c cannot be specified with --dont-generate') if options.dont_track: parser.error('-t cannot be specified with --dont-generate') if options.output_file: parser.error('-o cannot be specified with --dont-generate') # just return whether the input specified would be for part 2 if get_is_for_part2: return options.edge_weight_range is not None or options.vertex_pos_range is not None # initialize the random number generator global __RND_SEED global __rnd if options.random_seed is not None: __RND_SEED = options.random_seed else: __RND_SEED = unpack( 'Q', urandom(8))[0] # generate a truly random 8-byte seed __rnd = Random(__RND_SEED) def print_if_not_quiet(msg): if not options.quiet: print msg # determine how many vertices should be in the graph try: num_verts = int(args[0]) except ValueError: parser.error("NUM_VERTICES must be an integer") try: sne = options.num_edges if sne == 'c' or sne == 'complete' or sne is None: num_edges = edges_in_complete_undirected_graph(num_verts) else: num_edges = int(sne) if num_edges > edges_in_complete_undirected_graph(num_verts): parser.error( "-n may not be larger than NUM_VERTICES*(NUM_VERTICES-1)/2 (complete graph may not have self-loops or parallel edges)" ) elif num_edges < num_verts - 1: parser.error( "-n may not be less than NUM_VERTICES-1 (graph must be connected)" ) except ValueError: parser.error("-n must either be an integer or 'complete'") if options.precision <= 0: parser.error("-p must be at least 1") elif options.precision > 15: parser.error( "-p must be no more than 15 (doubles cannot accurately represent more than this)" ) if options.style is not None: parser.error("option -s is not yet supported") else: style_str = '' if options.edge_weight_range and options.vertex_pos_range: parser.error("option -e and -v are mutually exclusive") # determine the output file to use if options.output_file is None: path = get_path_to_generated_inputs() if options.vertex_pos_range or options.edge_weight_range: options.output_file = path + 'other-' + str(__RND_SEED) + '.g' else: options.output_file = path + '%s%u-%u-%s.g' % ( style_str, num_verts, num_edges, str(__RND_SEED)) # special use of the method ... just return the name we would use if get_output_name_only: return options.output_file # open the desired output file if options.output_file == 'stdout': out = sys.stdout elif not options.dont_generate: if options.may_use_existing: if os.path.exists(options.output_file): print_if_not_quiet( 'skipping input generation: %s already exists' % ppinput(options.output_file)) return 0 try: out = open(options.output_file, 'w') except IOError, errstr: die('generate_input: error: ' + errstr)
(str(get_density(num_verts, num_edges)), str(get_percent_of_max(num_verts, num_edges)))) if not options.dont_generate: about = gen_random_edge_lengths(num_verts, num_edges, min_edge_len, max_edge_len, options.precision, out) dimensionality = 0 min_val = min_edge_len max_val = max_edge_len mst_weight = -1 if options.dont_generate: print_if_not_quiet('graph not saved (as requested)') else: print_input_footer(num_verts, num_edges, about, out) print_if_not_quiet('graph saved to ' + ppinput(options.output_file)) if out != sys.stdout: out.close() # generate output with correctness checker, if desired if options.correctness: if options.dont_track: print >> sys.stderr, "warning: skipping correctness output (only done when -t is not specified)" return 0 try: mst_weight = compute_mst_weight(options.output_file) except CheckerError, e: print >> sys.stderr, e # record this new input in our input log if not options.dont_track:
def main(argv=sys.argv[1:], get_output_name_only=False, get_is_for_part2=False): usage = """usage: %prog [options] NUM_VERTICES Generates a connected graph with no self-loops or parallel edges. Output is sent to the default filename (""" + get_path_to_generated_inputs() + """/with V-E-SEED.g unless -e or -v are specified in which case a random filename is used.)""" parser = OptionParser(usage) parser.add_option("-c", "--correctness", action="store_true", default=False, help="compute and log the correct output") parser.add_option("-d", "--dont-generate", action="store_true", default=False, help="add the input to the inputs list file but do not generate it") parser.add_option("-l", "--inputs-list-file", metavar="FILE", help="set the file to store info about the new input to (default is usually fine)") parser.add_option("-m", "--may-use-existing", action="store_true", default=False, help="will not generate a new graph if the output file already exists") parser.add_option("-n", "--num-edges", help="number of edges to put in the graph [default: complete graph]") parser.add_option("-o", "--output-file", help="where to output the generated graph [default is inputs/[<STYLE>-]<NUM_VERTICES>-<NUM_EDGES>-<RANDOM_SEED>.g") parser.add_option("-p", "--precision", type="int", default=1, help="number of decimal points to specify for edge weights [default: %default]") parser.add_option("-q", "--quiet", action="store_true", default=False, help="do not log any extraneous information to stdout") parser.add_option("-r", "--random-seed", metavar="R", type="int", default=None, help="what random seed to use [default: choose a truly random seed using urandom()]") parser.add_option("-s", "--style", help="how to place edges [default: random with no self-loops or parallel edges]") parser.add_option("-t", "--dont-track", action="store_true", default=False, help="whether to log this input in our list of generated inputs") group = OptionGroup(parser, "Generation Type Options") group.add_option("-e", "--edge-weight-range", metavar="MIN,MAX", help="range of edge weights (range inclusive) [default: [0.1,100000]]") group.add_option("-v", "--vertex-pos-range", metavar="DIM,MIN,MAX", help="dimensionality of vertex positions and the range of each dimension (range inclusive) [not used by default; mutually exclusive with -e]") parser.add_option_group(group) (options, args) = parser.parse_args(argv) if len(args) < 1: parser.error("missing NUM_VERTICES") elif len(args) > 1: parser.error("too many arguments") # make sure --dont-generate isn't specified along with mutex switches if options.dont_generate: if options.correctness: parser.error('-c cannot be specified with --dont-generate') if options.dont_track: parser.error('-t cannot be specified with --dont-generate') if options.output_file: parser.error('-o cannot be specified with --dont-generate') # just return whether the input specified would be for part 2 if get_is_for_part2: return options.edge_weight_range is not None or options.vertex_pos_range is not None # initialize the random number generator global __RND_SEED global __rnd if options.random_seed is not None: __RND_SEED = options.random_seed else: __RND_SEED = unpack('Q', urandom(8))[0] # generate a truly random 8-byte seed __rnd = Random(__RND_SEED) def print_if_not_quiet(msg): if not options.quiet: print msg # determine how many vertices should be in the graph try: num_verts = int(args[0]) except ValueError: parser.error("NUM_VERTICES must be an integer") try: sne = options.num_edges if sne == 'c' or sne == 'complete' or sne is None: num_edges = edges_in_complete_undirected_graph(num_verts) else: num_edges = int(sne) if num_edges > edges_in_complete_undirected_graph(num_verts): parser.error("-n may not be larger than NUM_VERTICES*(NUM_VERTICES-1)/2 (complete graph may not have self-loops or parallel edges)") elif num_edges < num_verts - 1: parser.error("-n may not be less than NUM_VERTICES-1 (graph must be connected)") except ValueError: parser.error("-n must either be an integer or 'complete'") if options.precision <= 0: parser.error("-p must be at least 1") elif options.precision > 15: parser.error("-p must be no more than 15 (doubles cannot accurately represent more than this)") if options.style is not None: parser.error("option -s is not yet supported") else: style_str = '' if options.edge_weight_range and options.vertex_pos_range: parser.error("option -e and -v are mutually exclusive") # determine the output file to use if options.output_file is None: path = get_path_to_generated_inputs() if options.vertex_pos_range or options.edge_weight_range: options.output_file = path + 'other-' + str(__RND_SEED) + '.g' else: options.output_file = path + '%s%u-%u-%s.g' % (style_str, num_verts, num_edges, str(__RND_SEED)) # special use of the method ... just return the name we would use if get_output_name_only: return options.output_file # open the desired output file if options.output_file == 'stdout': out = sys.stdout elif not options.dont_generate: if options.may_use_existing: if os.path.exists(options.output_file): print_if_not_quiet('skipping input generation: %s already exists' % ppinput(options.output_file)) return 0 try: out = open(options.output_file, 'w') except IOError, errstr: die('generate_input: error: ' + errstr)
min_edge_len = 0 max_edge_len = 100000 print_if_not_quiet('density=%s pom=%s' % (str(get_density(num_verts, num_edges)), str(get_percent_of_max(num_verts, num_edges)))) if not options.dont_generate: about = gen_random_edge_lengths(num_verts, num_edges, min_edge_len, max_edge_len, options.precision, out) dimensionality = 0 min_val = min_edge_len max_val = max_edge_len mst_weight = -1 if options.dont_generate: print_if_not_quiet('graph not saved (as requested)') else: print_input_footer(num_verts, num_edges, about, out) print_if_not_quiet('graph saved to ' + ppinput(options.output_file)) if out != sys.stdout: out.close() # generate output with correctness checker, if desired if options.correctness: if options.dont_track: print >> sys.stderr, "warning: skipping correctness output (only done when -t is not specified)" return 0 try: mst_weight = compute_mst_weight(options.output_file) except CheckerError, e: print >> sys.stderr, e # record this new input in our input log if not options.dont_track: