创建绩效概况

创建绩效概况

性能概况是优化社区中使用的一种图表;下面是来自http://www.gamsworld.com/performancehttp://www.gamsworld.org/performance/profileGnuplot.gif

有关介绍,请参阅第 22.4 节Higham 和 Higham 的书Matlab 指南通俗地讲,该图表报告了y使用竞争方法进行的大量实验中,哪些百分比(在轴上)在x最佳结果的某个阈值(在轴上)范围内。

正式规范如下。

  • 假设您运行 m 个测试来比较 n 个现有方法。令 r_{ij} 为方法 j 对测试 i 获得的结果(错误、计算时间……等等;我们假设越低越好)。

  • 表现方法 j 在测试 i 上的得分定义为其结果与同一测试中最佳结果之间的比率,p_{ij} = r_{ij} / (min_j r_{ij})。注意 p_{ij} \geq 1。

  • 性能功能方法 j 的函数是 f_j(x) = 1/m * (测试次数 i,使得 p_{ij} \leq x),即方法 j 在最佳方法的因子 x 内的“概率”。请注意,对于每个 j,f_j(x) 在 x 中 (弱) 单调递增。

  • A绩效概况是所有函数 f_j 的图,如上图所示。

您是否知道是否支持在 tex 中创建性能配置文件?当然,这是一个非常简单的绘图,因此原则上可以预处理数据并返回一组可供绘图的 (x,y) 对,但如果绘图逻辑可以在 tex 中原生实现,那么就可以省去一步。

我在 的手册中没有找到任何内容pgfplots,而 是我的第一候选人。

如果有人希望实现它,这里有一组示例数据,采用 pgfplots 表格格式(列中的方法,行中的不同测试):

table{
  ode23    ode45   ode113
  1.26e-2  6.20e-3 1.56e-2
  2.41e-1  1.53e-1 1.97e-1
  3.74e-2  5.00e-2 6.68e-2
  3.37e0   6.45e0  7.86e0
  1.44e-1  1.56e-1 3.76e-2
  5.06e-1  1.07e0  1.5e0  
}

输出结果看起来或多或少类似于 Higham & Higham 书中的这张图片:

在此处输入图片描述

答案1

你显然是个数学家,或者说是相当接近数学家的人,因为你的句子总是以 (ε, δ) 的方式倒置。你必须倒着读数学,但正着读句子才能解码 :P

\documentclass[]{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.10,
             perf name table/.default=mytable}
\pgfplotstableread{
  ode23    ode45   ode113
  1.26e-2  6.20e-3 1.56e-2
  2.41e-1  1.53e-1 1.97e-1
  3.74e-2  5.00e-2 6.68e-2
  3.37e0   6.45e0  7.86e0
  1.44e-1  1.56e-1 3.76e-2
  5.06e-1  1.07e0  1.5e0  
}\mytable

\pgfplotstablegetcolsof{\mytable}% How many columns
\edef\mylastj{\number\numexpr\pgfplotsretval-1}% From zero to this num

%=========== Get the min of rows into a separate column =====================
\pgfplotstablecreatecol[
  create col/assign/.code={%
    \def\myrowmin{1e10}% Some big number that will be ignored in any min() invocation
    \pgfplotsforeachungrouped \x in {0,...,\mylastj}{%
    \pgfkeys{/pgf/fpu,/pgf/fpu/output format=sci}% To handle big numbers
    \pgfmathparse{min(\myrowmin,\thisrowno{\x})}%
    \pgfkeys{/pgf/fpu=false}%
    \let\myrowmin=\pgfmathresult%
    }%
    \pgfkeyslet{/pgfplots/table/create col/next content}\myrowmin%
  }
]{minperf}\mytable

%=========== Get each performance into a separate column =====================
\pgfplotsinvokeforeach{0,...,\mylastj}{
  \pgfplotstablecreatecol[
    create col/assign/.code={%
      \pgfmathparse{\thisrowno{#1}/\thisrow{minperf}}%
      \pgfkeyslet{/pgfplots/table/create col/next content}\pgfmathresult%
    }
  ]{perf-#1}\mytable
}
\makeatletter
\pgfmathdeclarefunction{colleqx}{2}{%
    \begingroup%
    \c@pgf@countd=0% No rows satisfy yet
    \pgfmathfloattoint{#1}%
    \pgfplotstableforeachcolumnelement{perf-\pgfmathresult}\of\mytable\as\mycompval{%
      \pgfmathfloatparsenumber{\mycompval}%
      \pgfmathfloatlessthan{\pgfmathresult}{#2}%
      \ifpgfmathfloatcomparison\advance\c@pgf@countd by1\fi%
    }%
    \pgfplotstablegetrowsof{\mytable}%
    \pgfmathparse{\c@pgf@countd/\pgfplotsretval}%
    \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}

\begin{document}\noindent
\pgfplotstabletypeset[]{\mytable} % Let's see if minperf and perffun-i works? 

\vspace{1cm}
\begin{tikzpicture}
    \begin{axis}[title=Performances,height=6cm]
        \addplot+[const plot] table[,x expr=\coordindex, y=perf-0] {\mytable};
        \addplot+[const plot] table[,x expr=\coordindex, y=perf-1] {\mytable};
        \addplot+[const plot] table[,x expr=\coordindex, y=perf-2] {\mytable};
        \legend{ode23,ode45,ode113}
    \end{axis}
\end{tikzpicture}

\begin{tikzpicture}
    \begin{axis}[title=Performance Functions,height=6cm,
                 legend pos=outer north east,grid=both,no marks]
        \addplot+[const plot,domain=1:5] (x,{colleqx(0,x)});
        \addplot+[const plot,domain=1:5] (x,{colleqx(1,x)});
        \addplot+[const plot,domain=1:5] (x,{colleqx(2,x)});
        \legend{ode23,ode45,ode113}
    \end{axis}
\end{tikzpicture}

\end{document}

此代码导致以下结果

在此处输入图片描述

一些评论;

  1. 我所做的是首先计算性能并将它们添加为列,正如您在第一个表中看到的那样。

  2. 然后我编写了一个小数学函数,它隐藏了表访问宏和计数内容,这样它在pgfplots调用时看起来像一个数学函数,但它实际上是每个列中的计数函数。当你调用它时colleqx(<column index>,<x value>)(例如列索引的行数大于或等于 x) 它会给出您提供的公式j = <column index>。索引编号从零开始。

  3. 整个机制基于表名\mytable。因为否则我知道我会花一整个晚上的时间。我不得不把它留给你 :) 但是它可以适用于任意数量的列和行(我希望)。


看到像 N. Higham 这样精通编程语言的人花费精力研究 matlab 之类的东西,却不研究合适的编程语言,我感到很心痛。不管怎么说,我跑题了。

相关内容