(自适应?)函数绘图的算法


21

我正在寻找算法来绘制可能具有或不具有奇异性的函数的标准2d图形。目的是编写一个“ Mini-CAS”,所以我对功能的类型没有先验知识,用户想画图。

这个问题很老,所以我想在文献中一定有一些标准算法。有一次,我没有太多通过谷歌找到参考文献的成功。

我确实找到了一种有趣的算法,即 “ YACAS-算法集”中的一种名为“自适应函数绘图” 的算法

简而言之:

  • 有标准算法吗?
  • 是否有针对已知难以绘制功能的测试套件?
  • 有哪些有趣的论文可供阅读?

2
也许使用“函数绘图”而不是“图形绘图”可以更好地理解该问题?首先,我误解了标题(图论)。
astrojuanlu 2012年

@ Juanlu001感谢您的建议。我改变了标题。
soegaard 2012年

当您说2D时,您是要绘制诸如类的一元函数,还是对以2D显示的具有不同颜色/阴影的二元函数()感兴趣?不同的值?f x y f(x)f(x,y)
Szabolcs 2012年

好吧,我的意思是绘制一个变量的函数。但是,我也想听听有关在两个变量设置中选择要评估的点的算法。我对听说颜色和阴影并不感兴趣。
soegaard,2012年

对于2D功能,请在此处查看我的问题和答案。我在这里所做的工作非常有限,并且对于任意功能而言效果不佳。另外,描述中缺少一些必要的步骤,否则该方法将无法正确收敛:我需要在网格的每个边缘的中间插入一个新的采样点,该采样点将在下一次重新三角化时消失。(续)
Szabolcs's 2012年

Answers:


10

我已经在GitHub上实现了Mathematica的自适应采样例程(这是一个C文件,转到头文件的源树)。很久以前,我在一本有关Mathematica的大书中找到了该例程的描述,并且一段时间以来,我一直在使用此实现的变体。它基本上在感兴趣的区域上进行了粗糙的线性采样,然后返回以细化高曲率区域。可能会遗漏一些非常鲜明的功能,但实际上,我发现这种情况极为罕见。该文件还包含并行版本。


1
那是哪本书?是我链接的那个吗?您知道版本5和版本6在其实现中发生了哪些确切变化吗?
Szabolcs,2012年

1
@Szabolcs:不,我相信这是在本书第4.1.3节中。该说明适用于Mathematica的非常旧的版本。较新的版本(可能从v6开始)可以检测垂直渐近线,并从图中删除虚假的垂直线。新版本肯定进行了大量复杂的符号预处理,以处理不连续性,未定义区域和分支切割。
维克多·刘

您正在谈论的符号预处理在文档中称为“排除检测”。可以通过将其定义为Exclusions -> None来隐藏函数的结构,也可以将其关闭。当我问这些更改时,这并不是我要指的。我相信算法会有所变化,因为v5和v6是在不同点采样的。现在,我无法再次在v5上进行测试。Plotf[x_?NumericQ] := ...
Szabolcs,2012年

《 Mathematica图形指南》对这个问题进行了很好的讨论。我特别喜欢还描述了该算法的不足之处。
soegaard 2012年

我再也找不到GitHub文件了,它移动了吗?
Andrei

12

了解其他CAS如何做到这一点可能会对您有所帮助。

f(x)(x(t),y(t))f(x)

  1. 从绘图域上的点按规则间隔的网格开始。(在Mathematica中,有一个参数控制取多少PlotPoints。)

  2. (x1,f(x1)),(x2,f(x2)),(x3,f(x3))x1+x22x2+x32

  3. 如果尚未达到迭代极限(MaxRecursion在Mathematica中设置),请从步骤2开始重复。

其中的一些内容在Stan Wagon撰写的《 Mathematica in Action》一书中进行了讨论,您可以在Google图书上找到

为了更好地控制计算函数的成本,我实施了该算法。这是步骤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 &]
  ]

7

函数图上的MathWorld网页包含对几篇论文的引用,这些论文似乎与自适应函数图有关。引用页面:

绘制图形的良好例程使用自适应算法,该算法在函数变化最快的区域中绘制更多点(Wagon 1991,Math Works 1992,Heck 1993,Wickham-Jones 1994)。Tupper(1996)开发了一种算法[...]

另一方面,我在Google上偶然发现了一篇论文

www.cs.uic.edu/~wilkinson/Publications/plotfunc.pdf

解释了如何正确选择域和其他内容。我希望它们对您有用。


1

我找到了这个主题,并认为我应该分享将其添加到Julia库Plots.jl 的开发人员问题页面。我们从Mathematica的实现笔记开始尝试了一系列技术,以期看到什么可以带来良好的效果。添加一些修剪,较小的扰动以使其不能精确地在间隔端点开始,递归限制和双重网格误差估计器都是“正确处理”所必需的。该线程还将您指向实现的开源代码。因此确实需要一些调整,但是添加这些功能使其变得非常健壮(根据测试,如线程中所示)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.