Archive for 二月, 2008

Using LAPACK in C

简单的说就是如何在C程序中调用Fortran子程序。我不想再学一门语言,所以直接调用库函数是最好的办法。google了一下,在VS2005里调试成功。简单来说你只需要:

  • 编译好的LAPACK库
  • 相应的头文件
  • 知道Fortran数组内存布局的特点
  • 知道如何在C程序中调用DLL
  • 就没问题。dll和头文件可以在这里下载。建议动手前查看一下头文件中的f2c.h,里面定义了一些常用的数据类型,混个眼熟。

    怎么在C程序中链接外部DLL库,这个和编译器有关,就不在这儿罗嗦了。

    主要的问题是怎样在C的数据类型和Fortran中的类型间进行转换。基本的类型,比如REAL, DOUBLEREAL之类的定义,都在f2c.h里写好了。最要紧的一点:Fortran中二维数组是按列存储的,而C是按行存储。当然,我个人的意见是干脆不要用C提供的多维数组,直接用一维数组,元素按Fortran惯例存放就行了,顺便定义一套宏什么的,用起来省事,看起来顺眼。此外,Fortran中函数传参是call by reference,和C的call by value截然相反,所以所有参数都必须是指针。记住这两条就差不多了。

    我要用LAPACK对角化Hamiltonian,感觉应该用zheev, compute all eigenvalues and, optionally, eigenvectors of a complex Hermitian matrix

    附精美范例一则,在VS 2005下编译通过:

    #include <stdio.h>
    #include "f2c.h"
    #include "zgeev.h"
    
    #define SIZE 3
    
    int main(int argc, char *argv[]) {
      doublecomplex A[SIZE][SIZE], b[SIZE];
      doublecomplex DUMMY[1][1],WORK[2*SIZE];
      doublecomplex AT[SIZE*SIZE];
      int i, j, ok, c1, c2, c3;
      char c4;
    
      /* initializing A */
    
      for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
          AT[j + SIZE*i].r = A[j][i].r;
          AT[j + SIZE*i].i = A[j][i].i;
        }
      }
    
      c1 = SIZE;
      c2 = 2*SIZE;
      c3 = 1;
      c4 = ‘N’;
    
      zgeev_(&c4, &c4, &c1, AT, &c1, b,
            DUMMY, &c3, DUMMY, &c3, WORK, &c2, WORK, &ok);
    
      if (ok == 0)
        for (i = 0; i < SIZE; i++)
          printf("%f + %fi\n", b[i].r, b[i].i);
      else
        printf("An error occured");
    
      return 0;
    }
    

    并非原创,来自Using LAPACK Routines in C Programs,略微做了些调整。

    阅读(352 次)

    Comments

    暴力求解24点

    是真正的暴力求解……穷举法。不过这个问题似乎也没有更好的方法了,各种算法除了暴力的程度,似乎也没有其他本质的区别。

    好久没写程序,今天写得这个75%是从网上参考过来的。那个产生所有可能的后缀表达式的算法很漂亮,产生所有排列的函数也很简洁。唯一的缺点是,这个方法会搜索大量重复的表达式,总的搜索空间是全排列数乘上Catalan数,比指数增长还要彪悍。但是对一般4个数的24点,这个低效率还体现不出来。此外,输出的表达式是后缀的,看起来不怎么顺眼。但是后缀转中缀又很麻烦,我就懒得再折腾了。

    import sys
    
    def add(a,b):
      return a + b
    def sub(a,b):
      return a - b
    def mul(a,b):
      return a*b
    def div(a,b):
      return float(a)/b
    
    ops = {add:’+‘, sub:’-‘, mul:’*‘, div:’/‘}
    
    def permute(seq):
      seqn = [[seq.pop()]]
      while seq:
        newseq = []
        new = seq.pop()
        for i in range(len(seqn)):
          item = seqn[i]
          for j in range(len(item) + 1):
            newseq.append(item[:j] + [new] + item[j:])
        seqn = newseq
      return seqn
    
    def _exprs(expr, stk_depth, vals, ops):
      if not vals and stk_depth == 1:
        yield expr
      if stk_depth > 1:
        for op in ops:
          for e in _exprs(expr + [op], stk_depth - 1, vals, ops):
            yield e
      if vals:
        for e in _exprs(expr + [vals[0]], stk_depth + 1, vals[1:], ops):
          yield e
    
    def exprs(vals, ops):
      return _exprs([], 0, vals, ops)
    
    def eval(expr):
      stack = []
      for e in expr:
        if callable(e):
          b = stack.pop()
          a = stack.pop()
          try:
            stack.append(e(a, b))
          except ArithmeticError:
            return None
        else:
          stack.append(e)
      return stack[0]
    
    def tostr(expr):
      ret = []
      for e in expr:
        if callable(e):
          ret.append(ops[e])
        else:
          ret.append(str(e))
        ret.append(’ ‘)
      return ”.join(ret)
    
    if __name__ == "__main__":
      vals = [int(x) for x in sys.argv[1]]
      goal = int(sys.argv[2])
      for p in permute(vals):
        for e in exprs(p, ops.keys()):
          if eval(e) == goal:
            print tostr(e)
    

    阅读(359 次)

    Comments

    新年好

    居然年三十了,同志们新年快乐。
    转载ws短信一条:工资翻个十倍,爱情出点小轨(这个免了),理想早日放飞,卧佛快点到来,百合多多灌水,BN再战三百回。
    我来继续ws:多收offer(此条送本宿舍申请团),多看动画(此条送所有宅男),多泡mm(此条特送Bcui和Bhui),多写禁书(此条送Bluo),等等等等。

    阅读(504 次)

    Comments (2)

    Mathematics in Physics

    我向来认为学数学的都是一等一的聪明人;学物理的就要稍微差一些。但是物理学家有个硕大的优势,就是他的研究对象有时远比研究者聪明。大自然往往出人意料,所以物理学影响数学的名例数不胜数,反过来的就逊色很多。以前高中时看杨振宁的演讲,谈到规范场和纤维丛的对应关系,真是漂亮的结果。二十世纪的数学肯定是几何和数学的天下,荣耀几乎都归于几何学家和拓扑学家。这个风气估计也影响到了物理学界,大家都喜欢把自己的结果拔高到topological的高度,这样才能吸引到足够的眼球和引用率。

    作为一个物理系学生,我自己对数学和物理之间关系的认识这几年也有很大变化,很大程度上受到了南大物理系氛围的影响,毕竟南大物理主攻凝聚态,和玄之又玄的超弦比起来,能量在几个eV的电子无疑是再实在不过的东西。以前刚进物理系的时候,满怀着对理论物理的热情,对场论和数学物理无比向往。数学与物理学结合最密切的分支,无疑是场论(包括弦论在内)。弦论对数学的要求更是到了令人发指的程度,我想我一辈子都不会搞明白代数几何到底在说些什么。当然,弄那么多复杂的数学结构,到底是好是坏,不是我一个外行人能判断的。不过从目前看来,弦论对数学的影响似乎还要在物理学之上,想想教皇E. Witten是Fields奖得主就明白了。

    还是回头谈谈我熟悉的凝聚态物理。其实在低能范围也能出现很多足够吓死人的数学结构,最具威慑力的估计还是geometric phase,都用不着量子场论,在所谓elementary的量子力学里都能出现non-Abelian gauge field和monopole,理所当然的有connection, curvature, fibre buddle。当然,我觉得玩那么玄的必要性是值得推敲的,它有如此清晰的物理意义,这些微分几何的数学解释更像是锦上添花。我比较感兴趣的Quantum Hall Effect,整数情形Hall电导可以用第一陈类表示。第一陈类是个什么东西?说实在我不懂,我更愿意把它看作Berry’s Phase,这已经足够了。第一陈类或许可以解释Hall电导的量子化和平台,除此之外似乎并不能给我们更多东西。FQHE的的水更深,场论的描述就是Chern-Simons Theory,很遗憾,是所谓的Topological Field Theory,下面可以做深的一脚下去就出不来的文章。

    经常能看到很多讨论学物理的需要掌握多少数学之类的文章。目前看来,除非要去挤场论这块高地,需要学很深的拓扑和几何,微积分,复分析和线性代数,加上一点点群论已经足够对付了。过于抽象和形式化,未必是好事。不过学点几何和拓扑也很有好处,有时候还是用得着的,所以我很想谁来教教我微分几何。

    话说前几天看到一篇剖析装逼艺术的网文,提到一个小tip:就是提到外国人名时能用原文就用原文。我自信提到欧美人时大部分能写原文,日文就比较麻烦,但是可以用罗马音混一下。我觉得更装的技术是提到美籍华人都是用让人看了牙疼的英文拼写,比如T. D. Lee, C. N. Yang, X. G. Wen,等等。

    阅读(334 次)

    Comments

    杂博

    今天早上起来,习惯性的开邮箱……看到一封Admission 2008……激动莫名。Boston College虽然物理排名不怎么样,但好歹是个offer,终于摆脱了三无状态。

    随后又有一条坏消息。UMich发面试通知;2月29日在上海。但是我没收到,难道这个学校就这样黄了?

    在家里实在无聊,银魂补完计划进度喜人,已经扫荡了50集。开始几天几乎是除了吃饭睡觉都在看,现在每天睡觉前看三集。所谓物极必反,我终于想起来还带了一堆paper回来看。但是做了一阵,数值模拟的结果总是不对,也很让人郁闷。

    阅读(443 次)

    Comments