Archive for February 2007

祝大家新年快乐~~   1 comment

祝大家新年快乐,万事如意,
合家安康,事业有成~~~

Posted February 17, 2007 by LostAbaddon in Uncategorized

MSDN与VS.NET2003说法不一致了   Leave a comment

正在和VB+VC#搏斗,结果就发现了一个MSDN与VS的一个“自说自话”的问题。
关于INTEGER与VALUETYPE,在MSDN中明确写到:

表示 32 位有符号的整数。

有关此类型所有成员的列表,请参阅 Int32 成员

System.Object
   System.ValueType
      System.Int32

这里INT32就是INTEGER。
随后,在VS中遇到一个转换,显示:“H:ResearchVisual BasicGANatureGAApplicationMain.vb(32): “Integer”不是从“System.ValueType”派生的,因此类型“Integer 的 1 维数组”的值无法转换为“System.ValueType 的 1 维数组”。”
 
且不说INTEGER数组和VALUETYPE数组之间的关系(后来想想,一个是Int*,一个是ValueType*,说不定并不具有Int与ValueType之间的派生关系,因而不能转换是可以理解的),就说它给的理由:“Integer”不是从“System.ValueType”派生的,这明显是睁眼说瞎话嘛!给VS写帮助的人是不是从来没看过MSDN啊?这也太离谱了吧?MSDN可是专门为VS服务的软件啊,竟然两者协调还这么弱?
再次鄙视MSDN。

Posted February 17, 2007 by LostAbaddon in 赛伯铁客

既然开始用BAIDU空间了   Leave a comment

既然开始用BAIDU空间了——其实我也不知道我能用它多少时间——那就总要写点东西来说说它。

不久以前写过一篇讨论我已经用过的各个不同BLOG系统的帖子(http://lostabaddon.spaces.live.com/blog/cns!EB06676D0B60BFBD!2504.entry),今天也就用同样的方式来看看BAIDU的这个空间怎么样。

首先,从最基本的BLOG功能入手。这方面BAIDU做得中规中矩,写的方面是应该有的都有,不应该有的一个没有,可有可无的绝对没有。是最基本也是最实用的套装组合。MS稍微所有的优势就在于写的方面有WLW和WLMD,这也是没办法的。
显示方面,也是,最简单最实用的组合,比MS好的就是不需要别人一定要注册为MSN成员。
管理方面,每个BLOG都有评论允许设定和帖子公开设定,这是比别的一些系统好的地方(比如MS就是一杆子打死型的)。不过MS也有一定的优势,就是“圈子权限”的设定,这样可以让部分人能看而部分人看不了。教育网BLOG的优点还是以前所说的,不同帖子的密码控制,虽然对实用型拥护来说这完全不必须,但是从我的角度来说还是很需要这样的功能的。
系统设定方面,还是MS的比较全面——有的时候甚至感觉是全面过了头——当然了,全面的部分理由是它需要和MS的MSN MESSENGER结合起来,这就要求它的功能要比别人的全面。
然后是STYLE方面。主题STYLE上,BAIDU和MS都很多姿多彩,但是BAIDU支持自创,这就比MS好了。似乎支持自创的不是很多,GOOGLEPAGE和ICQPAGE支持,不过这两个本来就是WEBPAGE系统,和BLOG不同,所以没有可比性。此外,BAIDU支持自传PIC,这个又比MS好了。布局方面和MS一致,但是可拓展栏上MS比较多比较好。
同样的,从WIDGET来看,MS SPACE支持的WIDGET相当多,许多还可以自创(OPERA也是),而这方面BAIDU显然没有——这也是主流,由此也可见MS的野心——想要改变主流,当然,这本身也是WEB2.0的一个趋势吧。
速度方面没话说,到底是过内服务器,速度再慢(比如QZONE)就太不象样了。
整合方面,BAIDU把自己所有已有的服务都整合了上去,但是,老实说,许多功能只是给人累赘的感觉而已,并不是太实用(这点要加上它自己在管理和控制方面的失败,使得BAIDU这个牌子已经不如当年那么响亮了——这点QQ已经彻底成了“榜样”了,QQ的牌子在我们这个不算很小的圈子里已经算是臭掉了)。

整体说来,BAIDU的这个空间集众家之长(有些是能力限制,集不了),一些地方还是相当出彩的,整体评价是好,和SINA、OPERA以及SPACE属于差不多的档次——这句话只是表明它比网海中的众多无名小站的BLOG系强而已。国外的比如WRITER和BLOGSPOT没用过,所以这里不好评价。

这里再度批判QZONE一次:能不能别老是更新QZONE程序啊?一个BLOG搞得这么复杂(都复杂到了一点用都没有的地方上去了)还被我找出过一个BUG,羞不羞啊。

Posted February 16, 2007 by LostAbaddon in 思维测地线

VB+VC#,果然有搞头   Leave a comment

昨天晚上总算正式开始写GAN了。
初步发现所谓INTERFACE的正式用途了:规定了CLASS的局部对外行为,是CLASS与CLASS之间的一种行为协议。
其实以前就知道这点,但是昨天用的时候才发现——早知道不用INTERFACE了,一个ABSTRACT的CLASS就什么问题都解决了。当然咯,对多模块之间的协同开发,用INTERFACE是有好处了:对不同模块之间的行为给予定义和规范而不用对一个模块的所有部分都进行定义。但是,这并不表示INTERFACE就是必须的了——我是这么想的。据说有个世界上顶级牛人开发程序从来不用INTERFACE,我想这其实只是一个习惯问题而已。如果一个程序从头到尾都是一个人开发的,那么用不用INTERFACE我感觉都遗言,哪怕不用ABSTRACT CLASS这样的手段也一样。INTERFACE不是必须的,就好比所谓的匈牙利命名法一样,只是一种良好的习惯而已,但并不阻止你拥有爱因斯坦鸡窝式的CODE。
昨天尝试了用VB.NET和VC#协同开发GAN,果然很有搞头。时不时就写出如下句子来了:
Public Sub GeneBuilder(int Length)
{
Dim Gene=new Gene(Length);
……
}
典型的结合过头……
用C#开发的DLL,用VB来引用。说白了,就是用C#开发KERNEL,用VB开发APPLICATION。之所以这么做,仅仅是出于好玩。最近的程序习惯用C#写了,打算回头重新开始用VB.NET。但是同时又感觉C不能放弃,所以就用这种协同开发的模式。如果可能,下次就是C++结合J2——不过似乎没有这种协同开发的IDE(ECLIPSE下有JDT和CDT,但是不知道怎样才能同时使用J和C),所以只能自己调用了。
由于GAN中含有FUNCTION的外部调用,所以就需要DELEGATE了。如果在C++中,这个问题很好处理,用一个POINT就搞定了——这也就是C++结合J2的难点:J2中没有指针。于是,昨天花了很大的力气研究了DELEGATE的传递。
其实并不是很难,但是由于之前一直没用到过DELEGATE(HANDLER不算,那是傻瓜化的),而且MSDN是出了名的垃圾(有用的资料需要你自己推敲,给你的资料都是白痴都知道的——最经典的一幕就是发生一个ERROR以后点选POPWIN中的HELP按钮,结果出现的MSDN帮助竟然是关于这个POPWIN而不是ERROR的,直接晕死。另一个经典场景就是把一个ERROR输入MSDN去查,结果查到的是这个ERROR所属CLASS的介绍,对于如何处理这个ERROR一点说法都没有。一个帮助程序开发成这样,MS的人都自杀去好了,没人拦的),而我自己的书都在学校,所以只能自己不断摸索到底是什么原因发生的错误以及如何处理这个错误。一直在想,难道是我买的MSDN是D版的,所以它生气了?应该不至于。这年头,除了售后服务,D和Z已经没什么区别了——何况一些所谓的售后服务已经成为了:出售以后继续为我们服务——这里的“我们”说的是厂家。

Posted February 16, 2007 by LostAbaddon in 世界叶

蛋炒饭   Leave a comment

我这个人非常懒,难得自己动手做一次饭,那也是因为菜都吃完了,又懒得出去店里吃。于是,今天中午就自己动手做了顿蛋炒饭。
放油的时候在怀念上一次自己动手丰衣足食是什么时候,下饭的时候就开始思索怎么做出一顿不同的蛋炒饭来。
加香肠、玉米等“作料”的时候还在感叹果然是“没有做不到只有想不到”,吃的时候直接就成了“没有不能吃只有不敢吃”。敢情长久不自己炒饭了,糖和盐混淆了……这蛋炒饭里放糖的味道还是第一次吃到。所幸的是饭和料还有多,便又炒了一份加香肠加玉米加……的蛋炒饭,爽得来~~
 
下MP3的时候路过BAIDU,诧异地发现它又开始跟风了:BAIDU空间……
就不能难得得领潮流一次,而每次都来跟潮流吗?
 
最近一直在玩《Knights of Honour》,游戏模式正好是我一直所希望的游戏形式的一种,赞一下。
继TOMB RAIDER IIV之后第二推荐的游戏就是KNIGHTS OF HONOUR了。当然,如果有KNIGHTS AND MERCHANT的话就更赞了。

Posted February 15, 2007 by LostAbaddon in 世界叶

一段代码,TSP问题的   Leave a comment

感觉解得还算可以,把二次竞争的次数设得大一点的话会更好。
MOFILE地址:http://pickup.mofile.com/4354347193218494
 
变异部分的代码(只给循环部分):
   for(tt=0,ttt=0;tt<life&&ttt<period;tt++,ttt++)
   {
    Paths=new ArrayList(num*8);
    for(i=0;i<num*2+back;i++)Paths.Add(ps[i]);//将父代拉入自然繁殖场
    MinL=ps[0].distance;
    MaxL=MinL;
    for(i=1;i<num*2+back;i++)
    {
     if(ps[i].distance>MinL)MinL=ps[i].distance;
     if(ps[i].distance<MaxL)MaxL=ps[i].distance;
    }
    A=(MaxN[index]-MinN[index])/(MaxL-MinL);//繁殖量生成函数参数
    B=(MinN[index]*MaxL-MaxN[index]*MinL)/(MaxL-MinL);
    for(i=0;i<num*2+back;i++)//父代变异后生成子代,并将子代拉入繁殖场
    {
     int fz=(int)(ps[i].distance*A+B);//计算父代的可繁殖量
     if(fz<1)fz=1;
     for(t=0;t<fz;t++)//交换变异
     {
      #region 第一种变异
      int sa,sb,la,lb;
      int[] np=new int[num];
      la=(int)(num/3*rd.NextDouble()*rd.NextDouble());//基因段A长度
      lb=(int)(num/3*rd.NextDouble()*rd.NextDouble());//基因段B长度
      sa=rd.Next(num-la);//基因段A位置
      sb=rd.Next(num-la-lb);//基因段B位置
      if(sb==sa)sb++;
      if(la==0)la=1;
      if(lb==0)lb=1;
      if(sb>sa)sb+=la;
      if(sb<sa&&sb+lb>sa)sb-=lb;
      if(sb<0)sb+=num;
      if(sb+lb>sa+num)sb-=(sb+lb-sa-num);
      if(sb>=num)sb-=num;
      if(sb+lb<=num)//没有回到头上的情况
      {
       if(sa>sb)//A段在B段后
       {
        for(j=0;j<sb;j++)np[j]=ps[i][j];//B段前不交换部分
        if(rd.NextDouble()>0.5)for(j=0;j<la;j++)np[sb+j]=ps[i][sa+j];//B段换A段正序
        else for(j=0;j<la;j++)np[sb+j]=ps[i][sa+la-1-j];//B段换A段反序
        for(j=0;j<sa-sb-lb;j++)np[sb+la+j]=ps[i][sb+lb+j];//A段与B段中间不交换部分
        if(rd.NextDouble()>0.5)for(j=0;j<lb;j++)np[sa+la-lb+j]=ps[i][sb+j];//A段换B段正序
        else for(j=0;j<lb;j++)np[sa+la-lb+j]=ps[i][sb+lb-1-j];//A段换B段反序
        for(j=0;j<num-sa-la;j++)np[sa+la+j]=ps[i][sa+la+j];//A段后不交换部分
       }
       else
       {
        for(j=0;j<sa;j++)np[j]=ps[i][j];//A段前不交换部分
        if(rd.NextDouble()>0.5)for(j=0;j<lb;j++)np[sa+j]=ps[i][sb+j];//A段换B段正序
        else for(j=0;j<lb;j++)np[sa+j]=ps[i][sb+lb-1-j];//A段换B段反序
        for(j=0;j<sb-sa-la;j++)np[sa+lb+j]=ps[i][sa+la+j];//B段与A段中间不交换部分
        if(rd.NextDouble()>0.5)for(j=0;j<la;j++)np[sb+lb-la+j]=ps[i][sa+j];//B段换A段正序
        else for(j=0;j<la;j++)np[sb+lb-la+j]=ps[i][sa+la-1-j];//B段换A段反序
        for(j=0;j<num-sb-lb;j++)np[sb+lb+j]=ps[i][sb+lb+j];//B段后不交换部分
       }
      }
      else
      {
       int[] pp=new int[num];
       int m=sb+lb-num;
       for(j=0;j<num-m;j++)pp[j]=ps[i][j+m];
       for(j=0;j<m;j++)pp[num-m+j]=ps[i][j];
       sa-=m;
       sb-=m;
       for(j=0;j<sa;j++)np[j]=pp[j];//A段前不交换部分
       if(rd.NextDouble()>0.5)for(j=0;j<lb;j++)np[sa+j]=pp[sb+j];//A段换B段正序
       else for(j=0;j<lb;j++)np[sa+j]=pp[sb+lb-1-j];//A段换B段反序
       for(j=0;j<sb-sa-la;j++)np[sa+lb+j]=pp[sa+la+j];//B段与A段中间不交换部分
       if(rd.NextDouble()>0.5)for(j=0;j<la;j++)np[sb+lb-la+j]=pp[sa+j];//B段换A段正序
       else for(j=0;j<la;j++)np[sb+lb-la+j]=pp[sa+la-1-j];//B段换A段反序
       for(j=0;j<num-sb-lb;j++)np[sb+lb+j]=pp[sb+lb+j];//B段后不交换部分
      }//基因变异完毕
      Path tmp=ps[i].Clone();
      for(j=0;j<num;j++)tmp[j]=np[j];
      tmp.Distance(pts);
      Paths.Add(tmp);//装入繁殖场
      #endregion
     }
     for(t=0;t<fz*2/3;t++)//倒序变异
     {
      #region 第二种变异
      int sa,la;
      Path tmp=ps[i].Clone();
      sa=rd.Next(num);
      la=rd.Next(num/2);
      int[] part=new int[la];
      if(sa+la<=num)
      {
       for(j=0;j<la;j++)part[j]=tmp[sa+la-1-j];
       for(j=0;j<la;j++)tmp[sa+j]=part[j];
      }
      else
      {
       int m=sa+la-num;
       for(j=sa;j<num;j++)part[j-sa]=tmp[j];
       for(j=0;j<m;j++)part[num-sa+j]=tmp[j];
       for(j=m;j<sa;j++)tmp[j-m]=tmp[j];
       for(j=0;j<la;j++)tmp[sa-m+j]=part[la-1-j];
      }
      tmp.Distance(pts);
      Paths.Add(tmp);
      #endregion
     }
     for(t=0;t<fz*2/3;t++)//段落移位
     {
      #region 第三种变异
      int sa,la,ta;
      sa=rd.Next(num);
      la=rd.Next(num/2);
      ta=rd.Next(num-la);
      int[] parta,partb;
      parta=new int[la];
      partb=new int[num-la];
      if(sa+la<=num)
      {
       for(j=0;j<la;j++)parta[j]=ps[i][sa+j];
       for(j=0;j<num-sa-la;j++)partb[j]=ps[i][sa+la+j];
       for(j=num-sa-la;j<num-la;j++)partb[j]=ps[i][j+sa+la-num];
      }
      else
      {
       for(j=0;j<num-sa;j++)parta[j]=ps[i][sa+j];
       for(j=num-sa;j<la;j++)parta[j]=ps[i][j-num+sa];
       for(j=0;j<num-la;j++)partb[j]=ps[i][sa+la-num+j];
      }
      Path tmp=ps[i].Clone();
      for(j=0;j<ta;j++)tmp[j]=partb[j];
      for(j=0;j<la;j++)tmp[ta+j]=parta[j];
      for(j=0;j<num-la-ta;j++)tmp[ta+la+j]=partb[ta+j];
      tmp.Distance(pts);
      Paths.Add(tmp);
      #endregion
     }
    }

Posted February 14, 2007 by LostAbaddon in 赛伯铁客

绍兴游   Leave a comment

又出去旅游了。这次的目的地是绍兴,一个我们一行四人都没有去过的地方。一起出去的人有我,HANSCH,曹导和秋秋。
我的旅行从前一天晚上就开始了。7号下午4点的时候我就从家里出发,前往了秋秋家。这么做的主要原因是从我家去火车站不方便,而火车又是一大早的,所以我们约好三个姓张的人一同从秋秋家出发去火车站——早上三点三刻就要起床的。
去他家以前说好了一起吃晚饭,所以当我由于路线不熟而屡屡中着6点三刻才到秋秋家的时候那实在是不好意思啊。他们一家人还有HANSCH等我到6点三刻,果然是辛苦的——虽然在我这里属于正常吃饭时间。饭后一起玩了幻想游戏4.8中的《神秘视线》,果然很挑战人的眼力(这种游戏形式这个学期我倒还正好想到过,打算用FLASH来实现的,结果现在发现已经有人用了。果然是英雄所见略同,狗熊所闻一样啊~~),三个人一起玩到了十点,都还没有过一关……睡觉的时候,秋秋先开始体验起了睡沙发的生活(这句话的含义大家自己去揣测吧),我和HANSCH一起睡大床。
一早三点三刻,三个人的手机一同吵了起来,这就拉开了一年中最早的一次起床的序幕。
我们要坐的139路首班车是在四点半,所以我们有很充足的时间来进行准备工作。秋秋的父母为我们每人准备了两个苹果两个大橘子还有许多小甜橘,都塞在我那空空的包里——因为我没有这么多准备,就带了银行卡出来而已,他们都准备得像小时候初中的时候出去春游一样,战备物资准备得好多啊。
四点半的头班车果然空得可以,我们三个姓张的都把衣服上的连衣帽戴着,让我第一个就想到了《终极一班》中的KO ONE尊,形象COOL得可以——那是说他的,到了我们这就成了CUTE了。到了虹口体育馆,几乎是空无一人的四川北路上逛到了多伦路,发现已经过了TAXI的夜宵时间,便叫了辆车,去了上海站。
我们比曹导早了半个小时到,便在软座候车室里打牌——这也就奠定了我们这次绍兴之旅的业余娱乐基调。直到曹导到了,我们也差不多上车了。
软座的车厢果然豪的——当然了,相比那些豪华包厢自然要逊色不少,不过已经非常好了。车上解决了早饭,然后临时改变了旅游计划,准备去五泄,从而把行程从两天的旅行拓为了三天。
下车后,买好了返程的票,便背着满肩的行李开始了东湖之旅。之前秋秋已经把所有旅游景点的路线都找好了(果然是一个细心的好人哪),所以我们直接就做K001路去了东湖景区。
东湖果然是一个好地方,更好的就是我们去的时候整个景点几乎就之后我们这四个人——这说的是我们所去的地方,在我们之前和之后也有不少人,但是几乎我们都没遇到,只是远远看到而已。因而,整个景点相当的清幽,加上本来风景就相当地好,所以整个旅游相当地令人满意。
门票是80的,由于秋秋忘了学生票这么一回事,所以这个景点我们多用了35。进去以后就看到了绍兴特产之一的臭豆腐,一问价格就立刻逃走了。随后就是很有特色的“乌蓬船”,但是一艘船只能坐两个人,而一艘船却需要40!本来想说“直接抢算了”,后来一想,它比抢还要好……于是我们决定不坐乌蓬船了,便往旁边的路开始爬山,这时听到那些划船的人发出了阵阵猥琐的笑声。
上山的路很好走,我们一路没有停留就到了山顶,虽然结果当然是相当气喘的,不过对于我们这种住在五楼的,这倒也不算太为难——何况我们以前也出来玩过,这种山自然不在话下——事后说明我们想错了。山顶先是一片茶树园,然后是一大片竹林,竹林边上有一个双层竹台,竹台对面是一个茶馆——价钱超贵。我们上去的时候正好碰到三位女士带着八个小孩,听他们说话应该也是上海去的。还有两名女生——不像工作了,工作了哪能这时候出来玩?然后我感叹了句果然是江南水乡(不知道什么意思的就只能自己去琢磨了)。我们在山顶看了看整个东湖,感叹了句“都取名叫湖了山还这么高,那下午的吼山要怎么地啊?!”然后就从他们上来的路下山,这个时候就发现我们出问题了——下山的路相比我们上山的路那可不是难走一点,是难走了一个数量级。我们再探头看看山下那些人是怎么走动的,立刻发现原来我们从下山的路上了,而从上山的路下……这上山的路当初就是开凿给上山用的,自然比下山的路难走多了——从下山的角度来说。下到了山下,才发现问题还没有完:原本这些人给我们订的路线就是先坐船来到这个地方,然后上山,从我们上来的地方下去,因而这里其实是一个湖中岛,是没路回去的……幸好一位划船的大爷免费把我们载过了岸。
从对岸我们一路走回去,发现这座名字为“绕门山”的不算大也一点不算小的山的峭壁原来峭得这么有个性——一片光整的壁就这么突了出来,一点都没有人工开凿的影子(当然,这山本来就是用人力弄出来的,但不是开凿),感觉非常的雄壮——HANSCH对东湖的总结就是“雄壮”,下午对吼山的总结是“雄奇”,导致第二天他用不出形容词了……
在一座湖心亭中我们解决了午饭,又拍了几张照,就结束了东湖之行。
当然了,这里说起来很简短,貌似没什么值得关注的地方一样,其实好地方多着呢。
在107车站上等了差不多一个小时,发现竟然一辆车都没有,打听了一下,发现107不久前刚改道到了东湖绕门山的另一侧,车牌还没来得及改……众人直接吐血身亡。打了辆车过去,发现这里的人还是相当老实淳朴的,不然像我们这种回头客一定要抬价了。
吼山是一个历史旅游景点,同时也是一个影视拍摄基地——陈宝国版(不是最新的陈道明版)的《越王勾践》和《西游记续》就是在这里拍的。据说这里是当年越王“卧薪尝胆”的地方,同时他还在这里放养了一些狗,所以当初叫做“狗山”,后来人们为了开发旅游景点,就改名为了“吼山”。整个地方还是相当瑰丽的——用HANSCH在山上的话说就是“雄奇”。
我们从左侧的山麓上的山,结果发现又是一个下山的路……直接来到了曹导称为“肉包子打狗”的地方。那里有两块奇石,下方的主体很直很粗,略有一点下细上粗的架势,而上方则各顶着两块风格迥异的石头,一个可以看做是“狗头”的形状,而另一个就能意会为“肉”了。一开始我们是认为一个是狗一个是权杖的,后来经曹导一点拨,就成了“肉”了。继续上山,就到了山顶的一个庙,后面还有一幢蛮大的房子,应该是给僧人住的,但是我只看到一个不是僧人的人在庙里。庙的样子很是不错,就是可惜少了点人气。
从另一侧下来,路过一个亭子,亭子后面没有路,但是有一个突出的崖。我和曹导很有兴趣过去探察一下,因为崖上坐着两个小孩,而那里并没有路上去,同时感觉从那里看下来风景一定很好。可惜,后来另两位不想去,所以就没去。真好去的话,只要从一个斜坡上做过去,翻过一大棵树然后就能从林中上去了——我观测下来是这样。
下山的途中经过一个很不错的谷,里面很是幽静,外面还有一个人造小塘,里面则都是石桌石椅,还有从上面不断滴下的山水——说白了就是泥水,因为山上没有河或者溪之类的。这个地方给人的感觉相当得好,藏得也真够隐蔽的,轻易是看不到的。果然山隐藏胜景啊。
到了这里,吼山一行也告结束。许多东西不是靠说得能说清楚的,还是要大家去看了才能领略。
回到了绍兴市区是两个小时以后的事情,因为107实在够贱,我们从吼山出来以后连续脱了两班车,最后还是靠三轮的士才回到的绍兴市区。途中吃了臭豆腐和呛饼(是这么写吗?不知道……)。
到了市区以后就开始找睡觉的地方。千寻万觅,最终找到一个不算差的小旅馆,名曰“美娟旅馆”。我们的心理价位是四个人100——很需要毅力的砍价目标,结果这里是一天四人60,比我们预期的都低,实在想不到。四人一间房,一床睡俩人,足亦。
解决了睡觉的地方,就开始出去觅食了。
别看解放路胜利路很繁荣,要找个符合我们要求的吃饭的地方还真不容易。首先要是中餐,然后要吃的是RICE,不是水饺面条,最后价格不能太离谱,像HAWAII大酒店或者咸亨直接就不在考虑范围内。最后是在一条类似步行街一样的地方找着了一家——屋里菜,就在状元楼对面。四人99,吃得也算过瘾,还喝了一瓶三年醇的古越龙山,服务员果然很有江南水香特色。
出来的时候,曹导语录正式启动。曹导看到一辆BMW,就说了两句。第一句是:“宝马讲究的是A呀。”第二句是:“这里一群宝马,你一辆奔驰都不好意思开出来。”第一句是需要说明的。平时曹导一直说的是类似这样的话:“巫妖带着一群石像鬼么要A过去的呀”——这是WARCRAFT玩多了的结果。
其实在找旅馆和饭店的时候,曹导语录就已经开始了,比如他说过:“这家宾馆墙上五个钟,所以不能住的呀”,到了第二天就是“这家饭店不行,前面停了一排宝马,我们一去就出不来了”,所以后来我们都用墙上挂着的钟的数目来判断一家宾馆的价位,而用饭店门前排着的轿车的数量来判断饭店的价钱——一次看到一辆Porsche,立刻判断这家酒店至少也要有四星,而咸亨前面的轿车那是一停车场一停车场地来算的。别说,这着还真管用。
晚饭后去一个新开的大卖场购第二天消费物资的物,那人叫一个挤呀。
回到旅馆以后大家依次先打了圈八十分,结果证明了我和HANSCH的星座组合相当好,随便打不记牌都打了个10比3。然后大家开始洗澡,于是改打两副牌的“七怪五二三”,结果为了压制大家囤积七的恶习,我和HANSCH提出了最后一圈手上有超过两张(不含两张)王牌的就算自爆了。这个新规则立刻就起到了意想不到的效果,大家一拿到王牌就像拿到了死亡通知书一样,扔之而后快。于是我又追加规定“第一张不能出七”,结果就导致了“抓住一切机会出王牌,没有机会创造机会”的打牌新局面。曹导洗澡完出来以后,由于出牌太猥琐,所以我再次追加新规定“一轮中不要牌的以后不能再要”和“连续三轮不出一张牌的就被憋死”。这两个规定一加,这个属于没有什么技术含量的牌立刻多了很多的趣味。秋秋连续三次被憋死,并且成为了第一个自爆掉的,而我也有一次头三局就憋死三家的经历。这种新牌法让我们突然感到异常地有趣,一直奋斗到了深夜1 点。
第二天起床以后出去买了鸡蛋饼地方早饭——因为一不小心就起床晚了。到了汽车西站,坐车一个半小时到了诸暨,然后59换57去五泄。59换57的时候,我们见识到了曹导“旷野的想象力”。他看到对面的一辆57,就说“57路应该就这一辆车,它绕一圈么总归就到五泄了”。
又坐了45分钟到了五泄,拍完照的时候发现一艘班船刚开走……于是多花了45分钟等下一班船。吃饭的时候曹导也说了不说语录级的话,可惜都没录下来。吃面包的时候曹导说他很喜欢吃果酱面包的,而且很有心得,结果一看我的方法立刻惭愧掉了——我用他涂在面包上的果酱的量涂面包,所不同的是他涂的是两片,然后夹一起,我是涂一片,然后折在一起。
五泄最外是一个人工湖——三面是山一面是坝。湖很漂亮,颜色翠绿,更重要的是三周的山上还很呼应地冒着水气,这个场景让人仿入仙境。碧绿的水和翠绿的山连在一起,别提多COOL,让人感觉特羡慕湖上捕鱼的渔民,每天都能面对这么壮丽的景色——到这里HANSCH开始感叹昨天不应该把“雄壮”和“雄奇”两个形容词用掉的,现在都没词了。
与我们同船的,还有两对情侣,让我们四人感觉自己很不应景。
通过一条山路来到一个小站,5元旅游车送去景点。当时我们不知道具体多远,就坐了,两分钟后后悔。下车后看到一条狗,我们打了一个招呼后那条狗竟然就一直跟着秋秋走了起来,旁边一对情侣中的女士立刻就说“哎呀,那是条母狗”,我们立刻道“哎呀,一语道破天机呀!”。这条狗于两小时后死亡。
来到的是双龙山庄——应该来源自山上的“西龙潭”和“毛龙潭”吧——它对面是一个车站,然后右面有一个很大的牌坊,上书“五泄”,然后进去就是一个寺庙——这里一般都会忽略旁边的一个岔道,而这个很重要。寺庙旁边是一个古色古香的竹楼餐馆,后面就是五泄的第五泄,旁边是一条山路往铁岭崖。
五泄就不一一描述了,总之,有机会的话还是一定要去看看的。虽然不比黄果树这样的泄界名宿——这名字听着还真别扭——但五泄的确是很值得一看的。
第一泄之后,我们就从东源到了西源区,穿过“山里人饭店”就开始了往山顶的路程。
这里有许多岔路,可惜我们时间不够所以没去。用曹导的话说,就是“那可条条都是不归路啊”。
一路上风景相当不错,拍了不少照片,随后就陡地往上,来到了山顶。
在山顶先是遇到了一拨绍兴人,然后是一拨上海人,还在亭子里讨论着IPOD的问题。
休息片刻后开始下山,15分钟就下到了底下。途中曹导的一句“我知道着铁栏杆为什么要一段左一段右了,那是因为一只手手一直扶着会冷死的,所以要经常换”成为了语录中的佳句。
来到山脚后所面临的问题,就是往哪边走。两边都有路,而我们显然不能两边都去。我根据水流方向判定了左面,结果还真对了。途中景色也绝对是怡人的,可惜的就是我们不能都去一次。
在一块山崖处,曹导“奔放的想象力”再开,指着它就说“这块石头长得很有想象力的,像头猪”,而我们另外三人死活没看出它是猪来。
走了差不多40分钟——远多于我们上山的时间了——我们还在这山谷中徘徊。老实说,这的风景真的是不错,不错到HANSCH一直说以后拉个女的过来就两全齐美了——哪两全自己揣摩去。还路过了一个没有人只有狗看守的茶室,以及亭子无数,美景万亿,这才回到了出发点——就是一旁那我们一开始都认为是“不归路”的岔道。
出来以后就想,如果以后有能耐在这里搞间别墅装个卫星每天直升机出入,哇,那就美得甭提啦。
然后,储备已久的内存总算得以释放,而就在这个过程中,那条被“天人”“一语道破”其真谛的母狗就这么挂了。从现场看是死于枪械设计,不过狗的尸首没看到,因为被人提进了屋,估计晚上会加菜。于是,我们开始揣测狗的死因。一开始还比较正常,后来曹导说了一个天人的:这狗其实以前吃过情花,本来没什么,今天看到秋秋,春心大动,情花之毒顿时爆发,于是,归了。
这个很“曹导语录”化的揣测算是在我们这炸开了锅,我们开始纷纷谴责起秋秋的不是,怎么这么就归了一条狗了呢?谁知道出去的时候我想走近路,结果猛犬当道,我们走着进去跑着出来了(一边跑一边还叫道“快走,不然就走不了啦!”)。这更加加深了我们的推测:秋秋果然招狗的。此后,零零总总有12条狗尾随过秋秋——还有一次是一条大的带领着三条小的一起跟——这还不算之前一天跟过秋秋的狗的数目。
五泄之行还是很值的,那里的风景雅致到不行。
晚上又逛了次街,感叹绍兴的许多建筑物果然是“有深意”的。一个体育馆样的建筑物造得怎么看怎么像Sydney的贝壳建筑Sydney Opern;旁边的一个购物中心则长的暴像南美的Maya Pyramid。
回到宾馆后,继续那种我们改造过的“七怪五二三”,相当有乐趣。曹导语录第三卷之打牌篇就是这个时候出的。最经典的一句是“要摸了才能干的呀”。
第三天是绍兴市内。走了次西圆、符山,然后去了次咸亨,差不多算是从环城北到环城南打了一个来回,在豪尚豪吃了顿西餐做午饭。
午饭我们四人吃了羊排、牛排和牛肋,68*4。西餐果然贵的。我吃的是Province羊排,里面除了羊排还有意大利通心面和一个荷包蛋。刀叉的用法我算熟了,所以吃起来感觉还可以。另三位就不行了,明显是用拿勺子的方式在拿叉子。
午饭后一算,我们这次出来平均每人用掉400有余,一些个人开销就不知道了。
回程是普通车,用了四个小时又一刻钟,回到了上海。途中的牌是斗地主,结果但凡是拿到了4个以上炸弹的地主都死于炸弹太多——我们规定炸弹是不能空炸的,而我提议的“三张五带一对五”的五俘虏则被判无效不能出。看着一个个地主死于资产过多,那叫一个爽啊。
到上海以后,曹导坐公交,HANSCH是一号线,我四好线而秋秋是三号线,大家就这么散了——后来我知道我其实可以坐隧三转82的,失误大了。
回到家的时候已经11点多了,那真叫一个累啊。
总体来说,这次绍兴之行相当满意。三天的风景都很好,特别是五泄,那真叫一个醉人啊。

Posted February 13, 2007 by LostAbaddon in 世界叶

日志0140——邮递员的第三篇   Leave a comment

到今天,关于GA解TSP的尝试已经进了尾声。
结果怎么说呢,还是比较满意的。
又尝试了几个新的手法,感觉都比较有挑战。
第一个手法,就是对初始基因的选择。前一篇说过了,初始基因对最后的结果有一定的影响,因为有些初始基因很容易就会陷入到局部极小区中,从而错过全局最小点。本来的初始基因完全是随机生成的,因而比较凭运气,而现在的初始基因则是按照我自己写的人工优化程序中的基因初始化条件所来进行的选择,因而比随机的初始基因来说,比较不容易走弯路。当然了,这个手法其实不算很好,因为它所带来的一个坏处就是基因比较单一,不如随机基因那么的多样性,这样其实对系统来说是不利的。不过,由于问题的解本身就比较单一,所以这种手段可以缩短GA的运行时间,因为少走了弯路,可以把更多的时间用在基因优化上。但是,对于那些我们不知道最优解是什么样的问题,这种手段就不太好了,因为会把一大部分可能通往最优基因的道路给封杀掉。
第二个手法,就是在每次保留的优等基因组中引入了一批劣等基因。这么做是因为被系统排除掉的劣等基因中有部分有可能是通往最优解的父基因,而且这么做本身也能丰富系统基因的多样性——不过由于我采用的是自体变异,不发生多体交换,所以多样性的优势在这里只体现在竞争力上,因而也就不明显了。引入这个手法以后,得到最优解的概率有了明显的提高,对20个节点的实验中尤其如此。
第三个手法,就是引入了我所谓的“上帝的改造”。对优等基因组中的部分基因进行认为的优化。优化的手法也是我自己的人工优化算法中所使用的,一个标准就是交换两个节点,取总路程最短的。这么做对基因段错置无效,但是却能得到段程局部优化,对最后稳定期有很大的帮助,可以迅速排除小扰动。
第四个手法,就是引入了一种新的变异手法。其实,它是我上次写算法的时候漏掉的……
还有一些程序级的小修改,比如二次竞争的参数等,也提升了系统的性能。
现在的结果,对20个基本可以一次拿下,25个也基本一次拿下,30个三次基本就能得到最优(把二次竞争系数改大以后,一次就可以了),50个的只能保证基本每次都是局部最优,真正的最优难以一次实现。
整体来说,算是基本完成了预期目标了,也深感欣慰。
这个经验对复杂网络这个课题还是很有帮助的。
昨天和杜建宏兄一同畅谈了一下午,很多想法都很让我振奋。
除了一起做一个项目以外,还打算利于多余的时间也学杜兄,开发一个为GA设计的接口框架,称为GA NATURE,为以后别的GA问题而做。目标是以后只要输入一组满足基因接口的初始基因,“上帝改造”算法函数(.NET中用DELEGATE,C++中用POINT,别的似乎不支持……),参数组,就能自动进行GA运算,以及对参数组的NN优化。
能做出来的话,以后研究GA问题就方便很多了。
今天下了FREE OPEN的OGRE,为了项目而奋斗。

Posted February 6, 2007 by LostAbaddon in 世界叶

日志0139——继续邮递员   Leave a comment

今天对昨天所搞的遗传算法做了一些所谓的“升级”。
结合了以前我的人工数学优化方法的一些思想,引入了“基因段”整体的自体交换和倒序等功能,对“繁殖量”的计算函数采用了神经网络的方法来得到参数——简单的二元参数函数,用神经网络似乎大材小用了。
参数的最后值很让我感到意外——劣等基因获得更高的繁殖量反而有利于系统获得最后解。神经网络的判断标准是10次遗传算法所的路径的平均路程,结果表明最劣等基因和最优基因以及基因保留数的比差不多为3:8:10的时候平均路程最短,而且就是最短路径——这个结果让我感到非常不可思议。当然了,这个比例是在对10个节点的模拟的情况下所得到的。其中,最离谱的一个比是1:11:10,最让人能接受的是8:8:10,但是平均路程很长。从后来的实验可以看出,这个比例是随节点数而变化的。由于对同一节点,多次所得比例分布在一个比较大的区域,所以事实上应该取什么比例我一点概念都没有,但是大致就在3:8:10上了。
此后,又引入了二次竞争:用遗传算法模拟10次,取最短。
在这个过程中,可以看出对邮递员问题,在我的遗传算法下,最终结果对初始基因组是有一定依赖性的,因为某些初始基因组很容易让最终的结果陷入某些极小而非最小的解域内——所谓“解域”是因为往往这些“错误引导”的解很集中在一个小范围内——这里的范围说的是路程范围。
同时,还看出的另一个问题就是VS.NET2003的RANDOM函数并不如我们所认为的一般随机。比如,用程序连续不断地进行10次模拟,和我用手点10次按钮的模拟,出来的结果是不同的。对于15个节点,手点的情况下总能出现一次最小路径,而用程序模拟的时候,却不一定。这个的原因我不知道。
说到随机函数RANDOM,这里有一点是要提醒大家的:小心使用这个类。比如,你在许多不同的VOID中申明了多个RANDOM,然后在一个MAIN中连续调用这写VOID,或者用一个FOR连续调用同一个VOID很多次,你会很诧异地发现最终的结果竟然都是一样的,而不是“随机”。理由是,RANDOM在无SEED的情况下系统时间作为SEED,时间单位是MS。但是,现代电脑速度是那么快,你在一个FOR中调用了100遍同一个VOID,结果1MS都没过去,因而这100个RANDOM的结果自然是始终完全相同的。
发现这个问题,是因为我的变异是建立在随机函数类RANDOM的基础上的,但是一开始变异的时候很诧异地发现100个子代基因和9个父代基因是完全相同的。问题的根源昭然若揭了。
因而,使用RANDOM的时候申明一个全局STATIC实例就好了,然后大家都用它。
这里也反映了VS.NET的开发人员也没注意到这点。如果注意到这点的话,应该就把RANDOM开发为SEAL的了,但是它现在不是。当然咯,如果VS的人认为这么封装比较有派头比较“高级”,那就再议了——秀才和兵是没共同语言的。
在完成了二次竞争以后,又修改了遗传算法的结束判据。现在的依据分两条:一,所得的最短路径保持一段时间不变;二,最优基因组保持一段时间不变。第一条表明该基因已经完全适应了环境,也就是已经最优了,而第二条则保证系统不会过早地进入程序阶段,因为过早进入的话,很可能就会陷入极小域而非最小域,同时,这也给新基因演化到最优提供了一个空间。
这里需要回头说一下神经网络所得的函数参数的意义了。优等基因所得的繁殖量小而劣等基因所得的繁殖量大,也反映了系统要求存在大量的候选基因,这样才能让大量同等基因可以相互竞争,防止某个基因垄断整个优等基因组,从而陷入区域。
现在的最终完成的程序,对最多16个节点,一般一次就能获得最后解——这已经比昨天的结果好很多了。对20个节点,需要多试几次,从而来选择最优路径,而对于更多的比如50个节点,则一点办法都没有,还是很混乱。
下一步,就要开始把GA和传统做法结合起来了。
我打算把我以前的三步走的方法和现在所用的GA的方法融合起来,这样应该就能获得对更多节点的更快优化程序了。

Posted February 4, 2007 by LostAbaddon in 世界叶

日志0138——遗传算法解决邮递员问题的尝试   3 comments

很早以前就听说杜建宏兄在用遗传算法解决邮递员问题。他是用C++写的解决方案。当时,我用人工数学优化的方法想了个三步走的方法来解决这个问题。今天在看《遗传算法》的时候突发奇想,想用遗传算法一效杜兄来解决该问题,便在C#下动手写起了程序。
基因用的是路径上的节点顺序,只能做自体交换,也就是变异,而无法做双体交换,因为两组基因的任意两部分交换基本不可能构成合理基因。这个做法中基因本身就是不完备的,因为书上说基因必须保证每个基因都有对应表现性,而我所选择的基因明显受到自身群分解性质的限制。当然咯,也可以把我的基因改成完备化的基因,但是感觉这么做意义不大。因为多体交换所带来的好处在这里似乎并体现不出来。在我所选择的变异方式下,交换似乎不是很必须。
我在“优胜劣汰”上也做了改进,每次保留一定数量优等基因,也就是路程短的基因,而无论它是父代的还是子代的。适应度函数也不再使用,因为程序实现的时候管你是否最大,最小一样可以。此外,不同适应度的路径允许生成的子代数(当然,是变异后的)也不同,这样更能体现“优胜劣汰”,因为生物的本性除了要自身延续,更主要的是本物种延续。
对10个节点的模拟效果不错,但是上升到50个的时候就出问题了。有交点出现就必然表明了路径非最优,而我的方法在50个节点的时候交点非常多。
此后改进了算法,基因的变异数量在不同时期不同。不再每次只改变一对基因的位置,而是可以改变多对。理由是我发现许多情况下要同时变动多个节点的顺序才能达到更短,仅一对反而更长。改进后的效果还是不明显。
分析了一下,主要原因是变异太过“随机”了,这样到了后期,许多关键部位无法变异到,反而使得结果是落在了“极小”点上而非“最小”点上。和数值求解方程值或者函数最值的遗传问题不同,这里问题的解域是相当离散的,应该能属于第一分离空间了吧(拓扑概念),而且数量一多以后,离散的程度就更大了,因而很难精确变异到最佳位置。这也许也反映了为什么自然界的生物并不都是“最佳”个体,而仅仅是相对来说的“很好”个体吧。
当然,也考虑过是不是列一个“淘汰基因表”,但是这样就和遍历法没区别了,最多就是随机遍历法而已,而且,这个做法和生物本身的进化规律也不符合。
从这方面来说,还是人工进行的数学优化的成功率比较高。至于效率就不知道了,因为前者已经随我的硬盘而去了,无从比较了。
很想看看成功的邮递员问题的遗传算法是怎么写的。
 
PS,“杜建宏”兄的这个名字在我的最新小说《You, AI》中可是一个响当当的名字哦,一出场自己还没动手风头就压过了三大主角了,打算以后重用这个人物呢——如果我能有毅力写完的话。

Posted February 3, 2007 by LostAbaddon in 世界叶