这两天帮欧洲的研究小组处理试验数据,就是计算试验数据的 Radial Distribution Funciton (RDF),发现50,000个数据点,用Mathematica处理起来非常吃力。已经开始用C++写程序了,后来尝试另一种方法,找到的计算时间上的差异。
问题定义:列举寻找N个点之间的距离。实现方法有两种,计算复杂度都是 O(N^2)。Mathematica里可以用两种方法实现:(1)利用Subset函数罗列2个点的组合,然后计算距离(Euclidean Distance);(2)利用循环。程序如下:
NumG = 500; Data = RandomReal[1, {NumG, 3}];
(* Method 1: Use Mathematica in-build function *)
DistDistance = {};
Timing[DistDistance = EuclideanDistance @@@ Subsets[Data, {2}];][[1]]
(* Method 2: Use loops *)
DistDistance = {};
Timing[For[i = 2, i <= NumG, i++,
For[j = 1, j <= i - 1, j++, {dx = Norm[Data[[i]] - Data[[j]]]; AppendTo[DistDistance, dx];
}]];][[1]]
测试程序里,都用了500个随机点。前一种是抽象语言,实现时间大概是0.128秒*;而后者属于底端的循环定义,尽然用了44.9秒!而且前者与数据点数量符合O(N^2),后者在1000个点以上就根本无法处理了。
看来以后用Mathematica还是要多使用程序里的函数形式。


*硬件环境,MacBook Pro 2014。
[补注] 这个看来是和内存利用相关的。第二种方法采用了AppendTo 函数,在每个循环里都在进行内存的读写。尺寸大的算例里,内存可以用到10G以上。计算程序已经优化。
[补补注] 需要提高计算效率,可以采用几种不同的函数定义方式。上文提到的方法,其中输入函数,并没有确定数据类型。这个其实是Mathematica的优点之一。但是要进行循环计算的时候,就反倒有效率上劣势。其解决方法是换用函数定义方法。下面是几个实测的算例,都是 10^7 次循环。
定义一,函数定义采用 ":=",或者"Function[]",计算时间在70秒左右;
定义二,采用 Compile[],需要预先定义函数类型,计算时间10秒左右;
定义三,采用 Compile[],类似定义二,但是在最后制定编译类型,CompilationTarget->"C"。计算时间3.5秒。定义入下图。

这个是一个在StackExchange 论坛上的问答 Q&A,关于Mathematica。问题十分简单,哪里去找学这个数学软件的资源。看看下面的回复,简直就是可以写出一本书的内容。不对,那信息量比一本,甚至一系列教程多得多得多得多得多(注意,这个不是口吃)。
Really good collection of resources for learning Mathematica, via goo.gl/OBVrcm
主要的是,这个回答(或者说回答系列)的详细程度,回答者的专业程度,让人叹为观止。另外就是可以看到社区的重要性,应该也是这些回答者们帮助他人的动力。这样的网络讨论,应该说是在英文社区中比较多见。
Wolfgang Pauli: "If god made the bulk, surfaces were invented by the devil."
We are using the Weierstrass-Mandelbrot function to generate virtual surface profiles. The following figures are the same surface (a self-affine surface), just using differnt resolution to reproduce plots. The important part about using such a fuction is that we can have an analytical form of the surface, including the possiblity to derive local curvature on the surface.



A real surface under AFM:

Referece:
Yan and Komvopoulos (1998) Contact analysis of elastic-plastic fractal surface. Journal of Applied Physics 84(7): 3617-3624.
AFM image of a sandblasted aluminum plate, in a 5 um x 5 um area.
Reconstructed from raw data in the TIFF file, converted from RGB to Grayscale.
Done in Mathematica.

今天算是弄通了Beamer里面的动画。之前,动画是我唯一让我留在MS PPT的理由,做模拟做实验,都是动画演示比较直观。Office的公式很差,而且换台计算机,可能还无法显示。还好有TeXPoint插件,利用LaTeX编译出来的公式图形来替代原生的Office公式输出。而Beamer输出的PDF文档,对于动画的支持一直不是那么好。于是还是暂时忍受PowerPoint做讲稿了。
最近,由于国际大搬家,换了一个地方以后,单位购买的Office版本从2003换到了2007,结果问题来了,以前一些讲稿,现在拿新版的Office一开,有不少地方需要调节。有一些由于版本的问题,不能在Wine里面的Office打开,还要到Windows原生的Office里转换格式,才能在Linux里面用。
想想以后不想如此折腾了,毕竟已经完全转到Linux,而且这个系统对于工作又不可或缺。于是查了几种方法来在PDF里加动画,找到了一个很满意解决方案。实际就是用一个animate包(英文说明,作者Alexander Grahn),然后用下面代码就可以实现:
\usepackage{animate}
...
\animategraphics[<options>]{<frame rate>}{<file basename>}{<first>}{<last>}
这个动画是由一个系列的图形文件构成的,自己定义动画的帧速<frame rate>,图形文件的目录和名称<file basename>,以及开始和结束的文件名称<first>、<last>。对于系列的图形文件,很多软件都有直接输出文件的命令。例如,下面的Mathematica输出命令就可以自动输出一系列的图片(文件名A1.jpg到A100.jpg):
Table[{image = "A" <> ToString[i] <> ".jpg";
Export[image, Show[G[i][[1]]]];}, {i, 1, 100}];
这里“G[i]”是一个带函数的图形输出命令。如果文件存在Figures目录下面,那么Beamer里调用下面命令就可以了。
\animategraphics[controls, buttonsize=3mm, height=0.3\textheight]{5}{Figures/A}{1}{100}
实际的例子可以看这里:slides.pdf。
如果动画是GIF、AVI格式之类的,也是有很多方法转换成系列图形的,例如ImageMagick,直接在命令行就可以完成转换。输出的带有动画的PDF文档,不再需要保存动画和图形文件,每次拷贝只需要一个文件就足够了。另外PDF的好处就是跨平台,在什么地方都可以看到一样的结果。
现在,用LaTeX/Beamer做讲稿的唯一问题已经解决。虽然做出来比较复杂的讲稿需要很多的时间,但是简单的东西,够用就可以了。另外,讲稿的目的,其实就是为了演讲者自己讲得清除,讲稿过于华丽倒是有反作用的。
PS,想到以后如果用PDF文档投文章,是不是可以直接插入动画了。如果从网上下载PDF,那么本地就可以直接看动画了。
近期评论