def test_as_stream(self): fid, fname = tempfile.mkstemp() os.close(fid) with as_stream(fname) as f: assert not f.closed assert hasattr(f, 'write') assert f.closed fid, fname = tempfile.mkstemp() os.close(fid) with as_stream(u"" + fname) as f: assert not f.closed assert hasattr(f, 'write') assert f.closed with open(fname) as f: assert not f.closed with as_stream(f) as f_: assert f is f_ assert not f.closed assert not f.closed
def pprint(self, stream=sys.stdout): """Prints a nicely formatted representation of the results. Parameters ---------- stream : file-like object or string, optional A file-like object or a filename where results should be written to. (default: ``sys.stdout``) """ with as_stream(stream) as stream: stream.write("solver results:\n") self.write(stream, prefix=" - ", pretty=True)
def write(self, stream, prefix="", pretty=False): """Writes results in YAML format to a stream or file. Parameters ---------- stream : file-like object or string A file-like object or a filename where results should be written to. prefix : string, optional A string to use as a prefix for each line that is written. (default: '') pretty : bool, optional Indicates whether or not certain recognized attributes should be formatted for more human-readable output. (default: False) """ with as_stream(stream) as stream: attrs = vars(self) names = sorted(list(attrs.keys())) first = ('solution_status', 'termination_condition', 'objective', 'bound', 'absolute_gap', 'relative_gap', 'nodes', 'wall_time') for cnt, name in enumerate(first): if not hasattr(self, name): continue names.remove(name) val = getattr(self, name) if val is not None: if pretty: if name == 'wall_time': val = time_format(val, digits=2) elif name in ('objective','bound', 'absolute_gap','relative_gap'): val = "%.7g" % (val) if name in ("solution_status", "termination_condition"): val = val.value stream.write(prefix+'%s: %s\n' % (name, val)) for name in names: stream.write(prefix+'%s: %s\n' % (name, getattr(self, name)))
def write(self, stream, prefix="", pretty=False): # type: (Union[IO, str], str, bool) -> None """Writes results in YAML format to a stream or file. Changing the parameter values from their defaults may result in the output becoming non-compatible with the YAML format. Parameters ---------- stream : file-like object or string A file-like object or a filename where results should be written to. prefix : string, optional A string to use as a prefix for each line that is written. (default: '') pretty : bool, optional Indicates whether or not certain recognized attributes should be formatted for more human-readable output. (default: False) Example ------- >>> import six >>> import pybnb >>> results = pybnb.SolverResults() >>> results.best_node = pybnb.Node() >>> results.best_node.objective = 123 >>> out = six.StringIO() >>> # the best_node is serialized >>> results.write(out) >>> del results >>> import yaml >>> results_dict = yaml.safe_load(out.getvalue()) >>> # de-serialize the best_node >>> best_node = pybnb.node.loads(results_dict['best_node']) >>> assert best_node.objective == 123 """ with as_stream(stream) as out: attrs = vars(self) names = sorted(list(attrs.keys())) first = ( "solution_status", "termination_condition", "objective", "bound", "absolute_gap", "relative_gap", "nodes", "wall_time", "best_node", ) for cnt, name in enumerate(first): if not hasattr(self, name): continue names.remove(name) val = getattr(self, name) if val is not None: if name in ("solution_status", "termination_condition"): if type(val) in (SolutionStatus, TerminationCondition): val = val.value elif pretty: if name == "wall_time": val = time_format(val, digits=2) elif name in ( "objective", "bound", "absolute_gap", "relative_gap", ): val = "%.7g" % (val) elif name == "best_node": assert isinstance(val, Node) if val.objective is not None: val = "Node(objective=%.7g)" % (val.objective) else: val = "Node(objective=None)" else: if name == "best_node": val = dumps(val) if not six.PY2: val = base64.encodebytes(val).decode("ascii") else: val = base64.encodestring(val).decode("ascii") val = "\n ".join(val.splitlines()) val = "!!binary |\n %s" % (val) else: val_ = "%r" % (val) if type(val) is float: if val_ == "inf": val_ = ".inf" elif val_ == "-inf": val_ = "-.inf" elif val_ == "nan": val_ = ".nan" val = val_ del val_ if pretty or (val is not None): out.write(prefix + "%s: %s\n" % (name, val)) else: assert val is None out.write(prefix + "%s: null\n" % (name)) for name in names: val = getattr(self, name) if pretty: out.write(prefix + "%s: %r\n" % (name, val)) else: if val is None: out.write(prefix + "%s: null\n" % (name)) else: val_ = "%r" % (val) if type(val) is float: if val_ == "inf": val_ = ".inf" elif val_ == "-inf": val_ = "-.inf" elif val_ == "nan": val_ = ".nan" val = val_ del val_ out.write(prefix + "%s: %s\n" % (name, val))
def summarize_worker_statistics(stats, stream=sys.stdout): """Writes a summary of workers statistics to an output stream. Parameters ---------- stats : dict A dictionary of worker statistics returned from a call to :func:`collect_worker_statistics`. stream : file-like object, or string, optional A file-like object or a filename where results should be written to. (default: ``sys.stdout``) """ import numpy wall_time = numpy.array(stats['wall_time'], dtype=float) queue_time = numpy.array(stats['queue_time'], dtype=float) queue_count = numpy.array(stats['queue_call_count'], dtype=int) objective_time = numpy.array(stats['objective_time'], dtype=float) objective_count = numpy.array(stats['objective_call_count'], dtype=int) bound_time = numpy.array(stats['bound_time'], dtype=float) bound_count = numpy.array(stats['bound_call_count'], dtype=int) branch_time = numpy.array(stats['branch_time'], dtype=float) branch_count = numpy.array(stats['branch_call_count'], dtype=int) load_state_time = numpy.array(stats['load_state_time'], dtype=float) load_state_count = numpy.array(stats['load_state_call_count'], dtype=int) explored_nodes_count = numpy.array(stats['explored_nodes_count'], dtype=int) work_time = wall_time - queue_time with as_stream(stream) as stream: stream.write("Number of Workers: %6d\n" % (len(wall_time))) div = max(1.0,numpy.mean(explored_nodes_count)) numerator = numpy.max(explored_nodes_count) - \ numpy.min(explored_nodes_count) if explored_nodes_count.sum() == 0: stream.write("Load Imbalance: %6.2f%%\n" % (0.0)) else: stream.write("Load Imbalance: %6.2f%%\n" % (numerator/div*100.0)) stream.write(" - min: %d\n" % (numpy.min(explored_nodes_count))) stream.write(" - max: %d\n" % (numpy.max(explored_nodes_count))) stream.write("Average Worker Timing:\n") queue_count_str = "%d" % queue_count.sum() tmp = "%"+str(len(queue_count_str))+"d" bound_count_str = tmp % bound_count.sum() objective_count_str = tmp % objective_count.sum() branch_count_str = tmp % branch_count.sum() load_state_count_str = tmp % load_state_count.sum() div1 = numpy.copy(wall_time) div1[div1 == 0] = 1 div2 = numpy.copy(queue_count) div2[div2 == 0] = 1 stream.write(" - queue: %6.2f%% [avg time: %8s, count: %s]\n" % (numpy.mean(queue_time/div1)*100.0, time_format(numpy.mean(queue_time/div2), align_unit=True), queue_count_str)) div2 = numpy.copy(load_state_count) div2[div2==0] = 1 stream.write(" - load_state:%6.2f%% [avg time: %8s, count: %s]\n" % (numpy.mean((load_state_time/div1))*100.0, time_format(numpy.mean(load_state_time/div2), align_unit=True), load_state_count_str)) div2 = numpy.copy(bound_count) div2[div2==0] = 1 stream.write(" - bound: %6.2f%% [avg time: %8s, count: %s]\n" % (numpy.mean((bound_time/div1))*100.0, time_format(numpy.mean(bound_time/div2), align_unit=True), bound_count_str)) div2 = numpy.copy(objective_count) div2[div2==0] = 1 stream.write(" - objective: %6.2f%% [avg time: %8s, count: %s]\n" % (numpy.mean((objective_time/div1))*100.0, time_format(numpy.mean(objective_time/div2), align_unit=True), objective_count_str)) div2 = numpy.copy(branch_count) div2[div2==0] = 1 stream.write(" - branch: %6.2f%% [avg time: %8s, count: %s]\n" % (numpy.mean((branch_time/div1))*100.0, time_format(numpy.mean(branch_time/div2), align_unit=True), branch_count_str)) other_time = work_time - objective_time - bound_time - branch_time - load_state_time div2 = numpy.copy(queue_count) div2[div2 == 0] = 1 stream.write(" - other: %6.2f%% [avg time: %8s, count: %s]\n" % (numpy.mean(other_time/div1)*100.0, time_format(numpy.mean(other_time/div2), align_unit=True), queue_count_str))