Example #1
0
    def __init__(self, show_missing=True, get_category=None, **kwargs):
        """
        ``kwargs['attributes']`` must contain exactly one attribute.

        If only one of the two configurations has a value for a run, only
        add a coordinate if *show_missing* is True.

        *get_category* can be a function that takes **two** runs (dictionaries of
        properties) and returns a category name. This name is used to group the
        points in the plot.
        Runs for which this function returns None are shown in a default category
        and are not contained in the legend.
        For example, to group by domain use::

            def domain_as_category(run1, run2):
                # run2['domain'] has the same value, because we always
                # compare two runs of the same problem
                return run1['domain']

        *get_category* and *category_styles*
        (see :py:class:`PlotReport <downward.reports.plot.PlotReport>`) are best
        used together, e.g. to distinguish between different levels of difficulty::

            def improvement(run1, run2):
                time1 = run1.get('search_time', 1800)
                time2 = run2.get('search_time', 1800)
                if time1 > 10 * time2:
                    return 'strong'
                if time1 >= time2:
                    return 'small'
                return 'worse'

            styles = {
                'strong': ('x','r'),
                'small':  ('*','b'),
                'worse':  ('o','y'),
            }

            PlotReport(attributes=['search_time'],
                       get_category=improvement,
                       category_styles=styles)

        """
        kwargs.setdefault('legend_location', (1.3, 0.5))
        # If the size has not been set explicitly, make it a square.
        params = kwargs.get('params', {})
        params.setdefault('figure.figsize', [8, 8])
        kwargs['params'] = params
        PlotReport.__init__(self, **kwargs)
        assert self.attribute, 'ScatterPlotReport needs exactly one attribute'
        # By default all values are in the same category.
        self.get_category = get_category or (lambda run1, run2: None)
        self.show_missing = show_missing
        self.xlim_left = self.xlim_left or EPSILON
        self.ylim_bottom = self.ylim_bottom or EPSILON
        if self.output_format == 'tex':
            self.writer = ScatterPgfPlots
        else:
            self.writer = ScatterMatplotlib
Example #2
0
    def __init__(self, show_missing=True, get_category=None, **kwargs):
        """
        ``kwargs['attributes']`` must contain exactly one attribute.

        If only one of the two configurations has a value for a run, only
        add a coordinate if *show_missing* is True.

        *get_category* can be a function that takes **two** runs (dictionaries of
        properties) and returns a category name. This name is used to group the
        points in the plot.
        Runs for which this function returns None are shown in a default category
        and are not contained in the legend.
        For example, to group by domain use::

            def domain_as_category(run1, run2):
                # run2['domain'] has the same value, because we always
                # compare two runs of the same problem
                return run1['domain']

        *get_category* and *category_styles*
        (see :py:class:`PlotReport <downward.reports.plot.PlotReport>`) are best
        used together, e.g. to distinguish between different levels of difficulty::

            def improvement(run1, run2):
                time1 = run1.get('search_time', 1800)
                time2 = run2.get('search_time', 1800)
                if time1 > 10 * time2:
                    return 'strong'
                if time1 >= time2:
                    return 'small'
                return 'worse'

            styles = {
                'strong': ('x','r'),
                'small':  ('*','b'),
                'worse':  ('o','y'),
            }

            PlotReport(attributes=['search_time'],
                       get_category=improvement,
                       category_styles=styles)

        """
        kwargs.setdefault('legend_location', (1.3, 0.5))
        # If the size has not been set explicitly, make it a square.
        params = kwargs.get('params', {})
        params.setdefault('figure.figsize', [8, 8])
        kwargs['params'] = params
        PlotReport.__init__(self, **kwargs)
        assert self.attribute, 'ScatterPlotReport needs exactly one attribute'
        # By default all values are in the same category.
        self.get_category = get_category or (lambda run1, run2: None)
        self.show_missing = show_missing
        self.xlim_left = self.xlim_left or EPSILON
        self.ylim_bottom = self.ylim_bottom or EPSILON
        if self.output_format == 'tex':
            self.writer = ScatterPgfPlots
        else:
            self.writer = ScatterMatplotlib
Example #3
0
    def __init__(self,
                 x_algo,
                 y_algo,
                 x_attribute,
                 y_attribute,
                 show_missing=True,
                 get_category=None,
                 **kwargs):
        """
        See :class:`.PlotReport` for inherited arguments.

        The keyword argument *attributes* must contain exactly one
        attribute.

        Use the *filter_algorithm* keyword argument to select exactly
        two algorithms.

        If only one of the two algorithms has a value for a run, only
        add a coordinate if *show_missing* is True.

        *get_category* can be a function that takes **two** runs
        (dictionaries of properties) and returns a category name. This
        name is used to group the points in the plot. If there is more
        than one group, a legend is automatically added. Runs for which
        this function returns None are shown in a default category and
        are not contained in the legend. For example, to group by
        domain:

        >>> def domain_as_category(run1, run2):
        ...     # run2['domain'] has the same value, because we always
        ...     # compare two runs of the same problem.
        ...     return run1['domain']

        Example grouping by difficulty:

        >>> def improvement(run1, run2):
        ...     time1 = run1.get('search_time', 1800)
        ...     time2 = run2.get('search_time', 1800)
        ...     if time1 > time2:
        ...         return 'better'
        ...     if time1 == time2:
        ...         return 'equal'
        ...     return 'worse'

        >>> from downward.experiment import FastDownwardExperiment
        >>> exp = FastDownwardExperiment()
        >>> exp.add_report(ScatterPlotReport(
        ...     attributes=['search_time'],
        ...     get_category=improvement))

        Example comparing the number of expanded states for two
        algorithms:

        >>> exp.add_report(ScatterPlotReport(
        ...         attributes=["expansions_until_last_jump"],
        ...         filter_algorithm=["algorithm-1", "algorithm-2"],
        ...         get_category=domain_as_category,
        ...         format="png",  # Use "tex" for pgfplots output.
        ...         ),
        ...     name="scatterplot-expansions")

        """
        # If the size has not been set explicitly, make it a square.
        matplotlib_options = kwargs.get('matplotlib_options', {})
        matplotlib_options.setdefault('figure.figsize', [8, 8])
        kwargs['matplotlib_options'] = matplotlib_options
        PlotReport.__init__(self, **kwargs)
        if not self.attribute:
            logging.critical('ScatterPlotReport needs exactly one attribute')
        # By default all values are in the same category.
        self.get_category = get_category or (lambda run1, run2: None)
        self.show_missing = show_missing
        self.xlim_left = self.xlim_left or MIN_AXIS
        self.ylim_bottom = self.ylim_bottom or MIN_AXIS
        if self.output_format == 'tex':
            self.writer = ScatterPgfPlots
        else:
            self.writer = ScatterMatplotlib
        self.x_algo = x_algo
        self.y_algo = y_algo
        self.x_attribute = x_attribute
        self.y_attribute = y_attribute