公告:本站正式转型为非交互式静态网站!
转型:本站将通过笔记和博客的形式继续为大家服务,关于 Mathematica 问答服务请移步至QQ群:365716997
联系:如有问题请联系QQ群管理员,或发送邮件至:lixuan.xyz@qq.com。
感谢:最后非常感谢大家多年来的支持与帮助!
参考《互联网跟帖评论服务管理规定》《中华人民共和国网络安全法》《网络信息内容生态治理规定》《互联网用户账号信息管理规定》

—— 2022-11-27

欢迎来到 Mathematica 问答社区

提问时请贴上文本代码

语法高亮:在编辑器中点击

被禁止的话题:广告破解

请阅读:《提问的智慧》

备用域名:mma.ooo

支持LaTex数学公式
行内公式标识符:\$ 或“$\backslash ($”+“$\backslash )$”,
行间公式标识符:\$\$ 或 “$\backslash [$”+“$\backslash ]$”

社区建议QQ群:365716997

分类

0 投票
5.0k 浏览
(*函数定义*)


GIRCF`Core[f_] := 
 Block[{RegularContinuedFraction`Mod = 
    If[FractionalPart@# === 0, 0, 1/FractionalPart@#] &, i, ii, j, k},
  Catch@For[k = {IntegerPart[f]};
    i = RegularContinuedFraction`Mod@f; j = -1, j < 233, j--,
    If[i === 0,
     Throw@k,
     If[IntegerPart@i === 0,
      AppendTo[k, Indeterminate]; Throw@k,
      AppendTo[k, IntegerPart@i]; 
      ii = RegularContinuedFraction`Mod@i; i =.; i = ii; ii =.;]]]]
GaussianIntegerMinkowskiQuestionMark[x___] := GIMQM@x;
GIMQM[x_] := GIMQM`Core@GIRCF@x;
GIMQM`Core[x_] :=
  Block[{AlternatingTotal = Total[# (-1)^Range[0, Length[#] - 1]] &},
    If[x[[-1]] === Indeterminate, Indeterminate,
     First@x + 2 AlternatingTotal@(1/2^Accumulate@Rest@x)]];

   
   
(*绘图用函数*)
Debug`PlotC`Core[fn_, xmin_, xmax_, ymin_, ymax_, step_] := 
 ParallelTable[
  Ember`PlotHue[fn, (Arg[fn] + \[Pi])/(2 \[Pi]), 1/(
   1 + 0.3 Log[Abs[fn] + 1]), 1 - 1/(1.1 + 5 Log[Abs[fn] + 1]), 
   1], {y, ymin + 0.0012, ymax, step}, {x, xmin + 0.0012, xmax, step},
   Method -> "FinestGrained"]

(*可行性测试*)
In[116]:= GIMQM[53/117]-MinkowskiQuestionMark[53/117]
GIMQM[2333.055+666.1005I]
GIMQM[2333.12345+666.54321I]

Out[116]= 0
Out[117]= (2333+666 I)+2 (-2^(-13+6 I)-2^(-11+5 I)+2^(-11+6 I)+2^(-11+7 I)-2^(-7+5 I)+2^(-5+7 I)-2^(-4+6 I)+2^(-4+7 I))
Out[118]= Indeterminate
(*本函数只有两种可能结果,一是正常出值,二是Indeterminate,本函数是闵可夫斯基问号函数在高斯复数上的推广。*)

(*绘图测试*)

Debug`PlotC`Core[GIMQM[x + I y], -5, 5, -5, 5, 0.1]
Plot[{GIMQM[x], MinkowskiQuestionMark[x]}, {x, -5, 5}]
Plot3D[Abs[GIMQM[x]], {x, -5, 5}, {y, -5, 5}]

(*不出图+鬼畜函数图像*)

==================================================================

依赖函数:

ComplexRationalQ[x___] :=
(Head@Re@x === Rational \[Or] Head@Re@x === Integer) \[And]
(Head@Im@x === Rational \[Or] Head@Im@x === Integer)
GaussianIntegerRegularContinuedFraction[fn___] := GIRCF@fn;
GIRCF[x_, dx_] := GIRCF`Core@Rationalize[x, dx];
GIRCF[x_] :=
If[ComplexRationalQ@x,
GIRCF`Core@x,
If[ComplexRationalQ@Rationalize@x,
GIRCF`Core@Rationalize@x,
If[ComplexRationalQ@Rationalize[x, 0],
GIRCF`Core@Rationalize[x, 0],
GIRCF`Core@Rationalize[N@x, 0]]]];



Ember`PlotHue[fn_, h_, s_, b_, a_] :=
Which[
fn === True, Hue[1/2, 0.8, 0.8, 0.5],
fn === False, Hue[1/2, 1, 0.1, 0.5],
fn === ComplexInfinity, Hue[1/8, 1, 0.8, 0.5],
Abs[fn] === Infinity, Hue[Arg[fn], 1, 1, 0.3],
fn === Indeterminate, Hue[2/3, 1, 1, 0.5],
fn === Overflow[] \[Or]
NumberQ[h] === False \[Or]
NumberQ[s] === False \[Or]
NumberQ[b] === False \[Or]
NumberQ[a] === False, 
Block[{Nfn = N[fn], Nh = N[h], Ns = N[s], Nb = N[b], Na = N[a]}, 
Which[
Nfn === Overflow[] \[Or]
NumberQ[Nh] === False \[Or]
NumberQ[Ns] === False \[Or]
NumberQ[Nb] === False \[Or]
NumberQ[Na] === False, Hue[1, 1, 1, 0.5],
Nfn === Underflow[], Hue[0.75, 1, 1, 0.5],
NumberQ[Nfn] === False, Hue[1/4, 1, 1, 0.5],
True, Hue[Nh, Ns, Nb, Na]]],
True, Hue[h, s, b, a]]

(*用于捕获异常值*)

 

分类:绘图 | 用户: EmberEdison (806 分)
修改于 用户:EmberEdison
我自己估计真有问题,也是GIRCF`Core的问题才对啊
恭喜你说对了,那个函数确实有问题。
改好了......请帮忙看看O O
待我晚上整理好发出来。
谢谢了么么哒~~~

1个回答

+3 投票
 
已采纳

问题蛮多的,本来思路已经整理好了准备写答案,然后发现原代码被改了不少。。只能先写一部分答案,然后再看看更新后的代码再说。。

首先是不出图。Debug`PlotC`Core[GIMQM[x + I y], -5, 5, -5, 5, 0.1]这句话死活运行不出来,理由很简单,自定义的Debug`PlotC`Core没有HoldFirst属性,所以这句话首先执行GIMQM[x + I y],其中x和y没有任何值,是个符号变量。那么单独运行GIMQM[x + I y],可以发现短时间内无法给出结果。

TimeConstrained[GIMQM[x + I y], 5, "Time Out"]
(*Time Out*)

因为你的GIMQM针对的是数值输入,但是在这里却出现了意外的x +I y符号输入,导致异常输入,至于异常输入后为什么就运算时间很长很长甚至可能无限长,和具体代码有关,由于没有细读代码,因此此处不再探讨这个异常输入会引发什么计算。

这个问题的修改方法也很简单,定义GIMQM的时候,加上个判断,也就是:

GIMQM[x_?NumberQ] := GIMQM`Core@GIRCF@x;

此时就可以正常画图了。

Debug`PlotC`Core[GIMQM[x + I y], -5, 5, -5, 5, 0.1] // 
  Image[#, ImageSize -> 300] & // AbsoluteTiming
 
(*9s 外加一张图*)

此外其他的话由于代码被修改了需要重新看。

在你原来的代码中,GIRCF`Core使用了迭代,也就是GIRCF`Core[n]的计算使用了GIRCF`Core[n-1]的值。然后运行代码出现了最主要的报错,也就是迭代层数超过1024。原因是如下:

fib[1] = fib[2] = 1;
fib[n_] := fib[n - 1] + fib[n - 2];
Trace[fib[8]]

可以看到fib[3]、fib[4]、fib[5]、fib[6]由于多次被调用,因此重复计算了很多次,一则造成计算时间很慢(特别特别特别慢),二则当n很大时,会造成迭代超过默认最大限制1024次:

fib[1] = fib[2] = 1;
fib[n_] := fib[n - 1] + 1
fib[2000]
(*报错,超过1024默认最大迭代次数*)

解决方法:使用记忆功能

fib[1] = fib[2] = 1;
fib[n_] := fib[n] = fib[n - 1] + 1
fib[100]
fib[1000]
fib[2000]
fib[4000]
(*最后一个会报错超过1024,因为4000到2000之间超过了1024*)
(*所以有时候还需要设置$RecursionLimit = Infinity*)

你的代码使用了ParallelTable,所以可以看得出来你觉得计算时间太长了。下面再说说计算效率的问题。

首先ParallelTable不是一定会比Table更快,这个我不具有一句话说明白的能力。总之不是所有情况下ParallelTable都会比Table快。当然在本文情况下,并行比不并行要稍微快那么一丢丢。在开启2核的情况下,下面这组参数,并行要36s,不并行要39s。

Debug`PlotC`Core2[fn_, xmin_, xmax_, ymin_, ymax_, step_] := 
 Table[Ember`PlotHue[fn, (Arg[fn] + \[Pi])/(2 \[Pi]), 
   1/(1 + 0.3 Log[Abs[fn] + 1]), 1 - 1/(1.1 + 5 Log[Abs[fn] + 1]), 
   1], {y, ymin + 0.0012, ymax, step}, {x, xmin + 0.0012, xmax, 
   step}]
Debug`PlotC`Core2[GIMQM[x + I y], -5, 5, -5, 5, 0.05] // 
  Image[#, ImageSize -> 300] & // AbsoluteTiming
(*39s*)
CloseKernels[]; LaunchKernels[2];
Debug`PlotC`Core[GIMQM[x + I y], -5, 5, -5, 5, 0.05] // 
  Image[#, ImageSize -> 300] & // AbsoluteTiming
(*34s*)

其次仔细观察Debug`PlotC`Core的定义,里面fn出现了4次,所以对于同样的x和y取值,GIMQM[x + I y]被计算了4次,造成重复计算。

解决方法是记忆化:

GIMQM[x_?NumberQ] := GIMQM[x] = GIMQM`Core@GIRCF@x;

此时并行的Debug`PlotC`Core需要时间是33s,稍微快了一点点,这说明CIMQM并不是Debug`PlotC`Core的运行瓶颈之处。那么到底是什么导致运算变慢呢。

Debug`PlotC`Core`一共就出现了那么几个函数,按照编写mma代码经验,你的GIMQM返回的是一个符号表达式(意思是不是数值表达式,虽然是个数),然后再求Abs,猜测这一步会很慢,验证一下。

GIMQM[6.38 + 6.21 I] // AbsoluteTiming
Abs[%[[2]]] // AbsoluteTiming
Abs[N[%%[[2]]]] // AbsoluteTiming
(*运行时间分别是0.000247、0.001004、0.000027*)

可以看出来GIMQM其实耗时没那么多,Abs耗时很多,然后你还Abs+Log重复计算了....

一个修改意见就是,如果你是纯粹画图,那么请在合适的地方切换到浮点数计算。具体代码我就不改了。

用户: 苹果 (2.2k 分)
采纳于 用户:EmberEdison
是内存重要还是计算效率重要,这是个具体问题具体分析的问题。又更新了一部分内容,估计没下文了,因为新代码懒得看。
最后那个切换问题。。我也不知道咋办,我怕越搞越坑爹;难道在ParallelTable里面放一个block然后N[fn]?
你猜。反正我是对这个问题没啥兴趣了,剩下的就是你自己专研了。
主要是这种绘图轰炸,如果分形函数的病态点比较多的话,特别是复分形,函数定义可能会玩坏,我试过内存占用上50多GB的情况。
总之谢谢了~~~~~~~
...