我目前正在研究冰雹序列(collatz 数字)。
我想创建一个这样的情节(来自维基百科):
但是我不知道这种图怎么叫(它既不是线图,也不是散点图或条形图或直方图,虽然看起来很相似)。
我想绘制从某个数字n
到 需要多少步1
。x 轴应为数字(从 1 到 M,M 尽可能大),y 轴应为步数。
由于我不知道上述那种图叫什么(而且我找不到名字),所以我使用了散点图:
遗憾的是,这似乎占用了大量内存。绘制 4100 (n,从 n 到 1 的步骤) 对成功了,但当我将其增加到 4150 对时,我得到了:
! TeX capacity exceeded, sorry [main memory size=3000000].
\endvarwidth ...\vbox \bgroup \unvcopy \@tempboxa
\@tempdima -\maxdimen \let...
l.28 \end{document}
我认为以下内容最终可以解决我的问题:
- 切换到 gnuplot(我不知道如何使用 gnuplot 读取 CSV 文件,而且我只使用过一次 gnuplot+LaTeX。有人有一个带有如何编译说明的最小工作示例吗?)
- 将图表类型切换为上面的图表(怎么称呼?)
- 实际上并没有在 csv 文件中写入数字 n,而是从行号中获取它(如何从下面代码中的 CSV 文件中获取 x 的行号?)
- 切换到另一种情节就像这里(我想这会更复杂,而且好像我必须使用 gnuplot / R。有人知道如何将它应用于我的问题吗?)
我写的所有代码都是在 GitHub 上。这是我目前编写的 LaTeX 代码:
\documentclass[varwidth=true, border=2pt]{standalone}
\usepackage[utf8]{inputenc} % this is needed for umlauts
\usepackage[ngerman]{babel} % this is needed for umlauts
\usepackage[T1]{fontenc} % this is needed for correct output of umlauts in pdf
\usepackage[margin=2.5cm]{geometry} %layout
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
axis x line=middle,
axis y line=middle,
enlarge y limits=true,
%xmin=0, xmax=2150,
%ymin=0, ymax=600,
width=15cm, height=8cm, % size of the image
grid = major,
grid style={dashed, gray!30},
ylabel=steps,
xlabel=$n$,
legend style={at={(0.1,-0.1)}, anchor=north}
]
\addplot[scatter,only marks] table [x=n, y=steps, col sep=comma] {../steps.csv};
\end{axis}
\end{tikzpicture}
\end{document}
我想绘制至少 100,000 个元素(如果可能的话最好是 10,000,000 个)。我该怎么做?
答案1
pgfplots,梳状图
感谢 Torbjørn T. 建议我看一下comb plots
。这让我能够绘制 7150 个(但不是 7200 个)数据点:
格努普特
十字架
您必须创建一个文件来告诉 gnuplot 要做什么。我将其命名为plot.gnuplot
:
set terminal latex
set output "plot-tmp.tex"
set datafile separator ","
set title "Collatz Number of steps"
plot '../steps.csv' every::1
然后你必须运行 gnuplot:gnuplot plot.gnuplot
这将生成一个可以包含在你的 LaTeX 文档中的“plot-tmp.tex”:
\documentclass{standalone}
\usepackage{graphicx}
\begin{document}
\input plot-tmp
\end{document}
这使我能够绘制 22300 个数据点(但不是 22350 个)。
梳状图
要获得梳状图,您必须在 plot 命令中添加“with pulses”。因此您的 plot.gnuplot 文件应如下所示:
set terminal latex
set output "plot-tmp.tex"
set datafile separator ","
set title "Collatz Number of steps"
plot '../steps.csv' every::1 with impulses
生成结果:
R
您可以(应该?)使用 R 将大数据绘制为 PDF 文件。R 可以处理包含 10,000,000 个数据点的 120 MB 文件。
为此,您必须安装 R 和 ggplot2(sudo apt-get install r-cran-ggplot2
)。
现在您可以从命令行启动 R sudo R
(必须是大写字母)来安装 hexbin install.packages("hexbin", dependencies=TRUE);
:(来源)
现在创建一个名为的文件analyze.R
并复制以下内容:
library(ggplot2)
mydata = read.csv("/home/moose/Downloads/algorithms/collatz/steps.csv")
# Prepare data
p<-ggplot(mydata, aes ( x=n,y=steps ))
# Plus means you add those options to the plot
p + geom_hex( bins=30 ) + opts(panel.background = theme_rect(fill='white', colour='white'))
执行它:R -f analyze.R
您将获得:
答案2
问题的表述看起来有点混乱。首先,它讨论了Wikipedia
链接中的图表,这是一个表示直方图的普通条形图:对于每个整数(从某个数字x
达到的步数),都有一个整数(该间隔内具有相同步数的数字数量)。请注意,范围不是很大,只是小于从数字获得的统计数据的单个点。下一个问题更简单,同时也更困难:绘制范围内测试的每个数字的步数。它更简单,因为不需要累积具有相同步骤的数字数量,而困难是......要绘制这样的图形,例如,一个“谦虚的数字” ,每个点都必须绘制(否则它只是某种无用的随机混乱)。假设每个条只有一个点宽,打印如果在,-轴的总宽度大约为1
1..100000000
y
x
x
600
100mln
x
100000
1200dpi
x
两米宽。
因此,此Asymptote
代码(没有任何额外程序)用于绘制与链接相同的图形Wikipedia
,这是从nMax=100000000
(100mln)数字中获得的统计数据。它在一台不太先进的笔记本电脑上后台运行大约需要 20 分钟。直方图数据在整数数组中累积stepCount
并打印到stdout
。输出还包括:
n=100000000
- 测试范围内的最大数量,highest=2185143829170100
- 整个测试期间达到的最大数量,maxStep=949
要达到的最大步数1
,maxStepArg=63728127
maxStep
需要步数才能达到的数量1
。
因此,从63728127
它开始就应该采取949
措施来获得1
。
collatz.asy:
import graph;
int nMax=100000000;
int highest=1;
int maxStepArg=1;
int[] arStep=array(nMax,0);
int stepMaxLimit=1000;
int[] stepCount=array(stepMaxLimit,0);
int steps(int nn){
int n=nn;
int m=0;
int nextn;
while(n>1){
if((n%2)==0){
nextn=floor(n/2);
++m;
}else{
assert(n<floor((intMax-1)/3),"too big n="+string(n));
nextn=3n+1;
highest=max(highest,nextn);
++m;
}
if(nextn<arStep.length && arStep[nextn-1]>0){
m+=arStep[nextn-1];
n=1;
return m;
}else{
n=nextn;
}
}
return m;
}
int maxStep=1;
int j;
for(int i=1;i<=nMax;++i){
j=steps(i);
++stepCount[j];
if(j>maxStep){
maxStep=j;
maxStepArg=i;
}
arStep[i-1]=j;
}
write("n="+string(nMax)
+", highest="+string(highest)
+", maxStep = "+string(maxStep)
+", maxStepArg = "+string(maxStepArg)
);
size(256,256,IgnoreAspect);
int nj;
real t;
pen barPen=rgb(0,0,0.5608)+opacity(0.6)+0.8pt;
guide g=(0,0);
for(int i=1;i<=maxStep;++i){
g=g--(i,stepCount[i])--(i+1,stepCount[i])--(i+1,0);
}
g=g--cycle;
fill(g,barPen);
xaxis(0,maxStep,RightTicks());
yaxis(0,max(stepCount),LeftTicks(beginlabel=false));
write(stepCount[0:maxStep+4]);
答案3
我通过 Asymptote 为这个 10 年前的问题制作了冰雹图。令人兴奋的是科拉兹猜想仍然开放。
为了绘制,我使用具有 3 个属性的struct
名称Collatz
:chain
表示链,len
表示max_value
链的长度(停止时间)和最大值。如果想要条形图,只需将其替换dot((i,d),2pt+red);
为
draw((i,d)--(i,0),blue);
在线编译需要几秒钟n=10000
。我还没有测试过离线运行。
// Collatz: the hailstone graph
// Run on http://asymptote.ualberta.ca/
struct Collatz {
int[] chain; // the Collatz chain
int len; // the length of the Collatz chain
int max_value; // the maximum of the Collatz chain
}
Collatz collatz_calculate(int n) {
Collatz c;
c.chain.push(n); // Initialise the chain with the first node n
c.len = 1; // Initialise the length chain as 1
c.max_value = n; // Initialise the maximum value as n
while (n > 1) {
n = (n % 2 == 0) ? (n # 2) : (3 * n + 1);
c.chain.push(n);
++ c.len;
c.max_value = max(n, c.max_value);
}
return c;
}
import graph;
size(12cm,8cm,IgnoreAspect);
int n = 10000;
for (int i=2; i < n; ++i) {
int d = collatz_calculate(i).len;
//draw((i,d)--(i,0),blue); // the bar graph
dot((i,d),2pt+red); // the hailstone graph
}
xaxis("$n$",BottomTop,LeftTicks);
yaxis("stopping time",LeftRight,RightTicks);
label("\bfseries Collatz conjecture: hailstone graph",point(N),2N);
shipout(bbox(5mm,invisible));