Example #1
0
    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)))
Example #2
0
    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))
Example #3
0
    def test_time_format(self):
        assert time_format(None) == "<unknown>"
        assert time_format(0.0) == "0.0 s"
        assert time_format(0.0, align_unit=True) == "0.0 s "
        assert time_format(0.0, digits=2) == "0.00 s"
        assert time_format(24.9) == "24.9 s"
        assert time_format(93.462, digits=3) == "1.558 m"
        assert time_format(93.462, digits=4) == "1.5577 m"
        assert time_format(93.462, digits=4, align_unit=True) == "1.5577 m "
        assert time_format(5607.72, digits=3) == "1.558 h"
        assert time_format(5607.72, digits=4) == "1.5577 h"
        assert time_format(5607.72, digits=4, align_unit=True) == "1.5577 h "
        assert time_format(134585.28, digits=3) == "1.558 d"
        assert time_format(134585.28, digits=4) == "1.5577 d"
        assert time_format(134585.28, digits=4, align_unit=True) == "1.5577 d "
        assert time_format(0.23334, digits=1) == "233.3 ms"
        assert time_format(0.23334, digits=2) == "233.34 ms"
        assert time_format(0.00023334, digits=1) == "233.3 us"
        assert time_format(0.00023334, digits=2) == "233.34 us"

        assert time_format(0.0009999, digits=1) == "999.9 us"
        assert time_format(0.00099999, digits=1) == "1.0 ms"
        assert time_format(0.00099999, digits=2) == "999.99 us"
        assert time_format(0.000999999, digits=2) == "1.00 ms"
        assert time_format(0.000999999, digits=3) == "999.999 us"
        assert time_format(0.0009999999, digits=3) == "1.000 ms"
        assert time_format(0.0009999999, digits=4) == "999.9999 us"
        assert time_format(0.00099999999, digits=4) == "1.0000 ms"
        assert time_format(0.00099999999, digits=5) == "999.99999 us"
        assert time_format(0.000999999999, digits=5) == "1.00000 ms"
        assert time_format(0.000999999999, digits=6) == "999.999999 us"
Example #4
0
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))