我正在寻找算法来为可能有也可能没有奇点的函数绘制标准二维图。目的是写一个“Mini-CAS”,所以对函数的类型没有先验知识,用户要图。
这个问题很老了,所以我想文献中一定有一些标准的算法。这一次,我通过谷歌找到参考资料的成功率并不高。
我确实找到了一种有趣的算法,即来自 “YACAS - Book of algorithm”的名为“Adaptive function plotting”的算法。
简而言之:
- 有标准算法吗?
 - 是否有用于已知难以绘制函数的测试套件?
 - 有哪些有趣的论文值得阅读?
 
我正在寻找算法来为可能有也可能没有奇点的函数绘制标准二维图。目的是写一个“Mini-CAS”,所以对函数的类型没有先验知识,用户要图。
这个问题很老了,所以我想文献中一定有一些标准的算法。这一次,我通过谷歌找到参考资料的成功率并不高。
我确实找到了一种有趣的算法,即来自 “YACAS - Book of algorithm”的名为“Adaptive function plotting”的算法。
简而言之:
了解其他 CAS 如何做到这一点可能会对您有所帮助。
据我所知,Mathematica 使用以下基本算法的变体来绘制单变量函数或参数曲线(我假设对于这个描述)。
从绘图域上规则间隔的点网格开始。(在 Mathematica 中有一个参数来控制取多少,叫做PlotPoints。)
查看每一对连续的线段(由三个连续的点定义,) 并在两个段的中间插入一个新的采样点 (和) 如果它们的角度大于阈值。
如果我们还没有达到迭代限制(MaxRecursion在 Mathematica 中设置),从第 2 步开始重复。
其中一些在 Stan Wagon 的 Mathematica in Action 一书中进行了讨论,您可以在 Google Books 上看到。
我之前实现了这个算法,以便更好地控制我的昂贵计算函数被评估了多少次。这是第 2 步的 Mathematica 代码:
nd[{points_, values_}] :=
Transpose@{(Drop[points, 1] + Drop[points, -1])/2,
Differences[values]/Differences[points]}
subdivide1d[result_, resolution_, maxAngle_: 10] :=
  Module[
    {deriv, angle, dangle, pos, nf},
    deriv = nd[result\[Transpose]];
    angle = ArcTan[#2] & @@@ deriv;
    dangle = Differences[angle];
    pos = Flatten@Position[dangle, d_ /; Abs[d] > maxAngle/180 Pi];
    pos = Union[pos, pos + 1];
    nf = Nearest[result[[All, 1]]];
    Select[deriv[[pos, 1]], Abs[# - First@nf[#]] > resolution &]
  ]
我已经在 GitHub 上实现了Mathematica 的自适应采样例程(它是一个 C 文件,上到头文件的源代码树)。很久以前,我在一本关于 Mathematica 的大书中找到了对该例程的描述,并且我已经使用这个实现的变体已经有一段时间了。它基本上在感兴趣的域上进行粗略的线性采样,然后返回以细化高曲率区域。可能会遗漏一些非常清晰的特征,但在实践中我发现这种情况非常罕见。该文件还包含并行版本。
函数图上的 MathWorld 网页包含对几篇似乎与自适应函数绘图相关的论文的引用。引用页面:
绘制图形的良好例程使用自适应算法,在函数变化最快的区域绘制更多点(Wagon 1991,Math Works 1992,Heck 1993,Wickham-Jones 1994)。Tupper (1996) 开发了一种算法 [...]
另一方面,在谷歌上我偶然发现了一篇论文
www.cs.uic.edu/~wilkinson/Publications/plotfunc.pdf
这解释了如何正确选择域和其他内容。我希望它们对你有用。
我找到了这个主题,并认为我应该分享开发者问题页面,以便将其添加到 Julia 库 Plots.jl。从 Mathematica 实现的注释开始,我们尝试了一系列技术来看看什么会产生好的结果。添加一些修剪、不完全从间隔端点开始的小扰动、递归限制和双网格误差估计器都是“让它恰到好处”所必需的。该线程还为您指出了实现的开源代码。所以它确实需要一些调整,但是添加这些功能使它非常健壮(根据测试,如线程中所示)。