Tuesday, March 24, 2009

矩阵求逆在3D程序中很常见,主要应用于求Billboard矩阵。按照定义的计算方法乘法运算,严重影响了性能。在需要大量Billboard矩阵运算时,矩阵求逆的优化能极大提高性能。这里要介绍的矩阵求逆算法称为全选主元高斯-约旦法。

高斯-约旦法(全选主元)求逆的步骤如下:

首先,对于 k 从 0 到 n - 1 作如下几步:

从第 k 行、第 k 列开始的右下角子阵中选取绝对值最大的元素,并记住次元素所在的行号和列号,在通过行交换和列交换将它交换到主元素位置上。这一步称为全选主元。
m(k, k) = 1 / m(k, k)
m(k, j) = m(k, j) * m(k, k),j = 0, 1, ..., n-1;j != k
m(i, j) = m(i, j) - m(i, k) * m(k, j),i, j = 0, 1, ..., n-1;i, j != k
m(i, k) = -m(i, k) * m(k, k),i = 0, 1, ..., n-1;i != k
最后,根据在全选主元过程中所记录的行、列交换的信息进行恢复,恢复的原则如下:在全选主元过程中,先交换的行(列)后进行恢复;原来的行(列)交换用列(行)交换来恢复。

实现(4阶矩阵)

float Inverse(CLAYMATRIX& mOut, const CLAYMATRIX& rhs)
{
CLAYMATRIX m(rhs);
DWORD is[4];
DWORD js[4];
float fDet = 1.0f;
int f = 1;

for (int k = 0; k <>
{
// 第一步,全选主元
float fMax = 0.0f;
for (DWORD i = k; i <>
{
for (DWORD j = k; j <>
{
const float f = Abs(m(i, j));
if (f > fMax)
{
fMax = f;
is[k] = i;
js[k] = j;
}
}
}
if (Abs(fMax) <>
return 0;
if (is[k] != k)
{
f = -f;
swap(m(k, 0), m(is[k], 0));
swap(m(k, 1), m(is[k], 1));
swap(m(k, 2), m(is[k], 2));
swap(m(k, 3), m(is[k], 3));
}
if (js[k] != k)
{
f = -f;
swap(m(0, k), m(0, js[k]));
swap(m(1, k), m(1, js[k]));
swap(m(2, k), m(2, js[k]));
swap(m(3, k), m(3, js[k]));
}

// 计算行列值
fDet *= m(k, k);

// 计算逆矩阵

// 第二步
m(k, k) = 1.0f / m(k, k);
// 第三步
for (DWORD j = 0; j <>
{
if (j != k)
m(k, j) *= m(k, k);
}
// 第四步
for (DWORD i = 0; i <>
{
if (i != k)
{
for (j = 0; j <>
{
if (j != k)
m(i, j) = m(i, j) - m(i, k) * m(k, j);
}
}
}
// 第五步
for (i = 0; i <>
{
if (i != k)
m(i, k) *= -m(k, k);
}
}

for (k = 3; k >= 0; k --)
{
if (js[k] != k)
{
swap(m(k, 0), m(js[k], 0));
swap(m(k, 1), m(js[k], 1));
swap(m(k, 2), m(js[k], 2));
swap(m(k, 3), m(js[k], 3));
}
if (is[k] != k)
{
swap(m(0, k), m(0, is[k]));
swap(m(1, k), m(1, is[k]));
swap(m(2, k), m(2, is[k]));
swap(m(3, k), m(3, is[k]));
}
}

mOut = m;
return fDet * f;
}
原算法 原算法(经过高度优化) 新算法
加法次数 103 61 39
乘法次数 170 116 69
需要额外空间 16 * sizeof(float) 34 * sizeof(float) 25 * sizeof(float)

Friday, March 6, 2009

Pseudocode of Gaussian Elimination

i := 1
j := 1
while (i ≤ m and j ≤ n) do
  Find pivot in column j, starting in row i:
  maxi := i
  for k := i+1 to m do
    if abs(A[k,j]) > abs(A[maxi,j]) then
      maxi := k
    end if
  end for
  if A[maxi,j] ≠ 0 then
    swap rows i and maxi, but do not change the value of i
    Now A[i,j] will contain the old value of A[maxi,j].
    divide each entry in row i by A[i,j]
    Now A[i,j] will have the value 1.
    for u := i+1 to m do
      subtract A[u,j] * row i from row u
      Now A[u,j] will be 0, since A[u,j] - A[i,j] * A[u,j] = A[u,j] - 1 * A[u,j] = 0.
    end for
    i := i + 1
  end if
  j := j + 1
end while

Algorithm for Gauss-Jordan elimination in Matlab

function [A, k] = rref (A, tolerance)

## Supress empty list warnings
eleo = empty_list_elements_ok;
unwind_protect
empty_list_elements_ok = 1;

[rows,cols] = size (A);

if (nargin < 2)
tolerance = eps * max (rows, cols) * norm (A, inf);
endif

used = zeros(1,cols);
r = 1;
for c=1:cols
## Find the pivot row
[m, pivot] = max (abs (A (r:rows, c)));
pivot = r + pivot - 1;

if (m <= tolerance)
## Skip column c, making sure the approximately zero terms are
## actually zero.
A (r:rows, c) = zeros (rows-r+1, 1);

else
## keep track of bound variables
used (1, c) = 1;

## Swap current row and pivot row
A ([pivot, r], c:cols) = A ([r, pivot], c:cols);

## Normalize pivot row
A (r, c:cols) = A (r, c:cols) / A (r, c);

## Eliminate the current column
ridx = [1:r-1, r+1:rows];
A (ridx, c:cols) = A (ridx, c:cols) - A (ridx, c) * A(r, c:cols);

## Check if done
if (r++ == rows) break; endif
endif
endfor
k = find(used);

unwind_protect_cleanup
## Restore state
empty_list_elements_ok = eleo;
end_unwind_protect
endfunction

Sunday, November 16, 2008

Using Endnote with LaTeX and BibTeX

[Updated: 31 March 2008] Important Update: There was a problem with the ens file that I uploaded earlier, If for some reason you havent got things to work try again. Thanks to Christian Milzow (Zurich) for noticing this error.


I wrote this guide because I had many references in Endnote that I wanted to use in my LaTeX documents. I had to figure all this out the hard way — by lots of trial and error. If you follow this guide it should be easy for you.

There are a few points to make: I have used every Endnote version since 4, but when I did my thesis I used version 9. This guide should work for other versions but I’m not sure. I also use MikTeX and WinEdt on Windows. I don’t have a clue about other configurations but they should still work with this guide.

In LaTex use natbib. It is by far the best referencing package. Put ''\usepackage{natbib}'' in your header. Then in your document where you want the Bibliograpy to appear add:

\bibliographystyle{plainnat}
\bibliography{name of your bib file}

I find plainnat pretty ugly so I wrote a better one bevbib4 you can use this, or write your own with custombib. Note don’t type in the file name extension in the LaTeX document. It will figure it out.

For all this to work you need a unique ID for every paper you cite, it is best to be consistent and keep it simple, for example my unique ID for my paper here is Weir04. This will print out as (Weir et al, 2004) [depending on the style used of course]. Your entries in your bib file should look like this:

@article{Weir04,
Author = {Weir, B. S. and Turner, S. J. and Silvester, W. B. and Park, D.-C. and Young, J. M.},
Title = {Unexpectedly diverse \emph{Mesorhizobium} strains and \emph{Rhizobium leguminosarum} nodulate native legume genera of New Zealand, while introduced legume weeds are nodulated by \emph{Bradyrhizobium} species},
Journal = {Applied and Environmental Microbiology},
Volume = {70},
Number = {10},
Pages = {5980-5987},
Year = {2004} }

Now the guide begins. I assume you have an endnote database (*.enl), back this up before continuing.

Preparing Endnote

  • To use my file " BibTeX_Export-custom.ens " you need to make these changes below. Or you can use the default file " BibTeX_Export.ens " (that I have made a couple of changes to) but you will need to use the "Label" field to type your unique ID. This may conflict with some websites that export references.
  • In Endnote go to: Edit -> Preferences -> Reference types.
  • For each type of reference you use click "modify reference types" scroll down and add "BibTeX" under the "custom 1" field. (don't do this bit if you are using the "Label" version)
  • Go to "display fields" and make Column 4 to display "Custom1" give it the title "BibTeX" (if you are using the Label version make the Column show "Label")
  • Go back to view your library. When you edit a reference by double clicking, a new field will appear (near the bottom) called "BibTeX" (or "Label"). In this field you type the unique ID (i.e. Weir04). Alternatively if you have a huge database you could use "Jabref" to automatically add these to your final BibTeX database. This software is also generally useful for managing your data once in BibTeX format.

Export the file as a BibTeX (*.bib) database

  1. Get my export filter style (Label version) or export filter style (Custom1 version) and save in the "Styles" directory of endnote. Then select that file using the style manager in: Edit -> Output Styles. Make sure this style is selected in the main view window.
  2. Go to: File -> Export. Save the file as a text (*.txt) file. Move this file to your LaTeX directory you are working with and rename to a *.bib file.
  3. Now when you cite a reference use the command \citep{Weir04} or \citet{Weir04} to get a parenthesis or text citation respectively (just try it out to see what happens)
  4. Run LaTeX or pdfTeX on your file twice then run bibtex then LaTeX or pdfTeX again a few times. Repeat if required. Or just use Texify. You should only have to run BibTeX again if you make a new *.bib file.
  5. With some luck the citation should be inserted and referenced at the end.

The fiddly bit is going back to those references and using proper LaTeX commands where necessary i.e. using \emph{Species name} (type this into the Endnote field) . This will of course look like rubbish if you use the same endnote database for MS Word documents. I keep two databases.

Notes on using the Style file

  • For electronic references I used the "book" reference type, and in the notes field add the url in this form: "URL: \url{http://www.example.com}" . Yes this is a hack. The note field in other reference types will not be used (see below).
  • When you add authors make sure they are in this format: "Sandberg, A. M." note the spaces, this is important. You can use full names (see below), but again: spaces.
  • Don't worry about en-dashes in the page ranges, this is taken care of automatically.

@book{Irwin05,
Author = {Irwin, Geoff and Walrond, Carl},
Title = {When was New Zealand first settled?},
Publisher = {Ministry for Culture and Heritage},
Address = {Wellington},
Series = {Te Ara -- The Encyclopedia of New Zealand},
Note = {URL: \url{http://www.TeAra.govt.nz/NewZealanders/MaoriNewZealanders/WhenWasNewZealandFirstSettled/en}},
Year = {2005} }

EndNote Export was not listed on your Output Styles menu?

If "EndNote Export" is not listed in the Edit -> Output Styles menu:

  • Select Open Style Manager.
  • Find the "EndNote Export" style and check it ON. Close this window.
  • Make sure that "EndNote Export" is now checked in the Edit -> Output Styles menu.
  • Select the references you want to transfer.
  • Choose File -> Export. . Make sure you are exporting the references as Text file Only, then click on OK.
Thanks to Nora Lieske for this tip.

Other Websites

The information on this page may not be exactly what you are looking for, some other websites which might be of help are:

Original Link: http://www.rhizobia.co.nz/latex/convert.html

Friday, September 12, 2008

Google出世(演义)

早期的搜索引擎,基本原理是关键词匹配。
http://www.ccthere.com/article/1751696譬如用户输入关键词"奥运会",搜索引擎的任务是查找与奥运会相关的网页。如果恰好有一篇网页,内容无他,"奥运会,奥运会,。。。",连说100遍。早 期的搜索引擎肯定把这个网页放在结果的首页,说不定还置顶,因为, 1. 网页内容中,"奥运会"这个关键词出现的频率非常高,2. 没有出现与奥运会不相干的内容。
早期搜索引擎的问题很明显,但是如何解决,却是仁者见仁智者见智。
http://www.ccthere.com/article/17516961996年,刚刚入学Stanford计算机系的Larry Page和Sergey Brin哥俩儿觉得,提高搜索引擎的准确性,或许可以从网页与网页之间的相互链接入手。譬如,网页A中提到奥运会时,给了一个链接,指向网页甲,那么网页 甲的内容很可能与奥运会相关。如果不仅网页A有这样的链接,而且网页B,C,D等等,都有类似的链接,那么网页甲的内容与奥运会相关的可能性就极高。
批评者说,这不是三人成虎吗?Larry心里也没谱,就跑去问他的导师,Terry Winograd。
http://www.ccthere.com/article/1751696导师外形很像爱因斯坦,想了一想,说,"先把Stanford校园网内所有网页收集下来,验证一下你们的想法。然后扩大到更大范围,再验证一下。如果验证 的结果不错,就把全世界互联网的所有网页,统统收集下来,做一个搜索引擎,上线,让全世界的人用,让全世界的人都来验证你们的猜想。"
两年后,1998年,Google上线了,三人成虎的猜想被实践证明是行之有效的。
http://www.ccthere.com/article/1751696Terry导师大手一挥,"把全世界互联网的所有网页,统统收集下来",可把Larry和Sergey哥俩儿忙坏了。互联网上有多少网页,统统收集下来, 需要占用多少硬盘空间?Larry和Sergey当时是博士班一年级学生,囊中羞涩,买不起那么多设备,没办法,开始四处讨钱。
托了七大姑八大姨,拐弯抹角找到了一个大款,名叫Andy Bechtolsheim。此公早年在CMU拿了EE的硕士后,跑到Stanford读CS/EE博士。没来得及拿到博士学位,就伙同Scott McNealy和Vinod Khosla,下海开公司去了,这个公司就是大名鼎鼎的SUN Microsystems。 Scott McNealy任SUN的CEO长达20多年,而Andy Bechtolsheim功成身退,跳出SUN自己开了一个小公司,后来这个小公司卖给了Cisco。
http://www.ccthere.com/article/1751696坊间传说,Larry和Sergey拜访Andy的时候,Andy正在电话上。冗长的电话,Larry和Sergey两个小伙子血气方刚,哪里耐得住这份性子,抬腿告辞。因为是朋友介绍,Andy有点过不去,就追到门口。问,"二位上门,有何需求?"
Larry和Sergey铁青着脸,说,"也没什么大事,就是想找点钱,做一个大规模文件系统。"
http://www.ccthere.com/article/1751696Andy问,"多大规模呢?存储什么数据?"
Larry和Sergey,"打算把互联网上所有网页都下载,然后建一个搜索索引。"
http://www.ccthere.com/article/1751696Andy,"把互联网上所有网页统统下载?!需要多大空间?几个Giga不行吧,几个Tera也不行吧,几个Peta,几个Zetta?。。。嗯,我看几个Googol也许才能撑得住。知道Googol吗?就是10的100次方,就是一个1后面拖100个0!"
Larry和Sergey,"是的,我们的确就是打算处理海量数据。"
http://www.ccthere.com/article/1751696Andy,"你们打算怎么做?买个EMC?那玩意儿很贵的哟,我可没那么多钱让你们烧。"
Larry和Sergey,"我们打算自己动手,用一堆PC做一个分布式集群。"
http://www.ccthere.com/article/1751696Andy,"PC?死机了怎么办?干嘛不用工作站,干嘛不用NFS?"
Larry和Sergey,"工作站比PC贵太多,NFS的不是很切合我们的需要。。。"
http://www.ccthere.com/article/1751696Andy挤出一点笑容,"好吧,小伙子们,给朋友一个面子,而且年轻人探险也是值得鼓励的。给你们10万吧,省着点花啊!"
Andy掏出支票本,一边签名一边问,"你们的公司叫什么?"
http://www.ccthere.com/article/1751696Larry和Sergey面面相觑,那时候他们还没来得及给公司取名。"要不就叫Googol吧?","Googol不太好拼写,要不改一改,叫Google吧。" Google这个名字从此诞生。

Monday, September 1, 2008

如何保持SSH链接不因IDLE时间过长而中断?

1. 修改/etc/ssh/sshd_config:
ClientAliveInterval 60
2. 重启SSH服务:
/sbin/service sshd reload
详细说明如下:
Using an OpenSSH server's ClientAliveInterval, it is possible for the ssh server to send periodic "keep alive" messages to the ssh client, keeping the connection open indefinitely. This is useful when a firewall or other packet filtering device drops idle connections after a certain period of time. Note that this is different from the KeepAlive directive in ssh_config.

From the sshd_config manpage:

ClientAliveInterval
Sets a timeout interval in seconds after which if no data has
been received from the client, sshd will send a message through
the encrypted channel to request a response from the client. The
default is 0, indicating that these messages will not be sent to
the client. This option applies to protocol version 2 only.


Example (send "keep alive" messages every 5 minutes) on Red Hat Linux:

1. Add ClientAliveInterval 300 to /etc/ssh/sshd_config

2. Reload the sshd server configuration with /sbin/service sshd reload

Note: you may want to configure the ClientAliveCountMax value in sshd_config to set the number of times that "keep alive" messages are sent. If ClientAliveCountMax number of "keep alive" messages are not acknowledged by the ssh client, the connection is terminated by the ssh server. The default value of 3 should be sufficient for most users.

Friday, August 29, 2008

傅立叶变换的意义与卷积

(一)傅立叶变换的物理意义

傅立叶变换是数字信号处理领域一种很重要的算法。但是该算法到底有何意义呢?

要知道傅立叶变换算法的意义,首先要了解傅立叶原理的意义。傅立叶原理表明:任何连续测量的时序或信号,都可以表示为不同频率的正弦波信号的无限叠加。而根据该原理创立的傅立叶变换算法利用直接测量到的原始信号,以累加方式来计算该信号中不同正弦波信号的频率、振幅和相位。

和傅立叶变换算法对应的是反傅立叶变换算法。该反变换从本质上说也是一种累加处理,这样就可以将单独改变的正弦波信号转换成一个信号。

因此,可以说,傅立叶变换将原来难以处理的时域信号转换成了易于分析的频域信号(信号的频谱),可以利用一些工具对这些频域信号进行处理、加工。最后还可以利用傅立叶反变换将这些频域信号转换成时域信号。

从现代数学的眼光来看,傅里叶变换是一种特殊的积分变换。它能将满足一定条件的某个函数表示成正弦基函数的线性组合或者积分。在不同的研究领域,傅里叶变换具有多种不同的变体形式,如连续傅里叶变换和离散傅里叶变换。

傅立叶变换属于调和分析的内容。"分析"二字,可以解释为深入的研究。从字面上来 看,"分析"二字,实际就是"条分缕析"而已。它通过对函数的"条分缕析"来达到对复杂函数的深入理解和研究。从哲学上看,"分析主义"和"还原主义", 就是要通过对事物内部适当的分析达到增进对其本质理解的目的。比如近代原子论试图把世界上所有物质的本源分析为原子,而原子不过数百种而已,相对物质世界 的无限丰富,这种分析和分类无疑为认识事物的各种性质提供了很好的手段。

在数学领域,也是这样,尽管最初傅立叶分析是作为热过程的解析分析的工具,但是其 思想方法仍然具有典型的还原论和分析主义的特征。"任意"的函数通过一定的分解,都能够表示为正弦函数的线性组合的形式,而正弦函数在物理上是被充分研究 而相对简单的函数类,这一想法跟化学上的原子论想法何其相似!奇妙的是,现代数学发现傅立叶变换具有非常好的性质,使得它如此的好用和有用,让人不得不感 叹造物的神奇:

1. 傅立叶变换是线性算子,若赋予适当的范数,它还是酉算子;

2. 傅立叶变换的逆变换容易求出,而且形式与正变换非常类似;

3. 正弦基函数是微分运算的本征函数,从而使得线性微分方程的求解可以转化为常系数的代数方程的求解.在线性时不变的物理系统内,频率是个不变的性质,从而系统对于复杂激励的响应可以通过组合其对不同频率正弦信号的响应来获取;

4. 著名的卷积定理指出:傅立叶变换可以化复杂的卷积运算为简单的乘积运算,从而提供了计算卷积的一种简单手段;

5. 离散形式的傅立叶变换可以利用数字计算机快速的算出(其算法称为快速傅立叶变换算法(FFT))。

正是由于上述的良好性质,傅里叶变换在物理学、数论、组合数学、信号处理、概率、统计、密码学、声学、光学等领域都有着广泛的应用。

在图象处理上的应用
傅立叶变换是图像处理中最常用的变换。它是进行图像处理和分析的有力工具。

傅立叶变换的数学定义
传统的傅立叶变换是一种纯频域分析,它可将一般函数f(x)表示为一簇标准函数的加权求和,而权函数亦即f的傅立叶变换。设f是R上的实值或复值函数,则f为一能量有限的模拟信号,具体定义如下:

2、图像傅立叶变换的物理意义

图像的频率是表征图像中灰度变化剧烈程度的指标,是灰度在平面空间上的梯度。 如:大面积的沙漠在图像中是一片灰度变化缓慢的区域,对应的频率值很低;而对于地表属性变换剧烈的边缘区域在图像中是一片灰度变化剧烈的区域,对应的频率 值较高。傅立叶变换在实际中有非常明显的物理意义,设f是一个能量有限的模拟信号,则其傅立叶变换就表示f的谱。从纯粹的数学意义上看,傅立叶变换是将一 个函数转换为一系列周期函数来处理的。从物理效果看,傅立叶变换是将图像从空间域转换到频率域,其逆变换是将图像从频率域转换到空间域。换句话说,傅立叶 变换的物理意义是将图像的灰度分布函数变换为图像的频率分布函数,傅立叶逆变换是将图像的频率分布函数变换为灰度分布函数。

(二) 卷积的意义
参见剑桥的课件,写得很好。