比较各种Dijkstra最短路算法的matlab代码

整整一天,我都在网络上寻找Dijkstra算法的matlab代码。我找到了许多,然而,它们全部都不能满足我的需要。
后来我只好参考wiki给出的正确的dijkstra算法,自己写了个代码。wiki给出的算法在此:
http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
摘录如下。

1 function Dijkstra(Graph, source):
2 for each vertex v in Graph: // Initializations
3 dist[v] := infinity // Unknown distance function from source to v
4 previous[v] := undefined // Previous node in optimal path from source
5 dist[source] := 0 // Distance from source to source
6 Q := the set of all nodes in Graph
// All nodes in the graph are unoptimized – thus are in Q
7 while Q is not empty: // The main loop
8 u := vertex in Q with smallest dist[]
9 if dist[u] = infinity:
10 break // all remaining vertices are inaccessible
11 remove u from Q
12 for each neighbor v of u: // where v has not yet been removed from Q.
13 alt := dist[u] + dist_between(u, v)
14 if alt < dist[v]: // Relax (u,v,a)
15 dist[v] := alt
16 previous[v] := u
17 return previous[]

作为教训,我总结一下网络上能找到的大多数dijkstra算法的matlab代码的优劣。
1.“Dijkstra最短路算法通用Matlab程序”
这套代码可以说是国内传播最广的dijkstra算法的matla实现,可以在许多网站找到,例如这里:
http://www.labfans.com/bbs/t3095/
它的输入是赋权邻接矩阵和起始点,输出是起始点到各点的距离和最短路树。代码在这里
然而!它是错的!
用这套代码可以得出起始点到各点的距离,然而算法得出的最短路树完全是错的,甚至用示例数据得到的最短路树都根本不可理解。算法根本就没按正确的dijksta算法的思路走。
2.Dijkstra 算法 matlab程序
这套算法也流传甚广,链接在这里:
http://www.9414.net/Article/jsjjjs/biafh/200504/735.html
这套算法很简短,功能也很简单。它的输入是赋权邻接矩阵,输出是起始点到各点的距离和最短路树。使用示例数据可以得到正确的结果。缺点是它仅能算出从点1到其他各点的距离。
代码在这里
后来我又发现了第二个缺点:这算法也是错的。从根本上就是错的,只是恰好能把示例数据算对而已。
3~4.来自mathworks的各种dijkstra代码
它们应该都是对的,然而太复杂,不适合我的应用;它们各自具有其应用范围,我没有依次尝试,就放在这里而已。
代码A只能提供从某点到某点的距离,然而不提供从某点到其它任意点的最短路树。
代码B能够提供从某点到其它任意点的最短路树,但是它是基于地图的,需要提供每个点的坐标。
5.正确的,可以给出从某点到其它任意点的最短路树的dijkstra算法代码
我写的,应该没问题了。
输入是赋权邻接矩阵和起始点,输出起始点到其他各点的距离和最短路树。
代码在此

数据预处理初见成果

在长达数月的时间里,我都在与java和oracle搏斗。开始的时候,把所有数据直接写进数据库,一天的数据要算大半天。往后一点,先进行预处理再写进去,需要六小时左右。再后来,换了一台更好的电脑,同时发现一个巨大bug,于是一个正面因素和一个反面因素导致我的程序还是得运行五六个小时。
直到今天。
上周基本上都在赋闲状态,因为实在被自己的程序折磨惨了。用了Jprofile优化程序,却发现绝大多数的时间都花在读文件和写数据库的过程中。跟导师说实在是没有进一步优化的空间了,导师说那就把这两个过程优化下呗,总是有法子的。
好吧,他是对的。
我从那天起才开始认识到,其实这两个过程也是可以优化的啊。读文件慢,因为我是一个变量一个变量地读。查了查资料,网上说你可以一下子读几个k么。写数据库确实慢,我大不了直接写进文件里去嘛。
于是我花了大约大半个小时,把读文件的过程重写了一遍,然后删除了所有跟数据库有关的代码。
我计算了一天的数据,居然只需要11分钟!!!!
这是个重要的启示。
无论如何,太阳终于出来了。

JProbe Plugins for Eclipse 安装体验

JProbe Version: 8.1.0
软件简介:一款Java代码、内存和覆盖率分析工具。
主要特性:覆盖浏览器和源代码视图-快速分离未检测代码和死代码;
批处理模式-能以批处理模式运行,方便的集成建立/测试系统;
报表-以XML、纯文本、CSV或者HTML格式输出覆盖范围报告,用以定制分析;
快照合并-合并多个平台运行的整个覆盖数据;
Eclipse IDE集成,提供了Eclipse插件,可在Eclipse中直接进行内存分析和代码覆盖率测试。
下载:
JProbe for AIX – BIN Format
JProbe for Linux for x86 and x64 – BIN Format
JProbe for Solaris – BIN Format
JProbe for Solaris x86 – BIN Format
JProbe for Windows – EXE Format
JProbe Plugins for Eclipse
JProbe Installation Guide
JProbe Release Notes
JProbe User Guide
JProbe Reference Guide
JProbe Plugins for Eclipse Guide
JProbe Demos and Tutorials
破解方法(请使用正版软件):
安装Jprobe后,
方法1:替换client-support.jar目录中的\com\sitraka\licensing\ValidateSignature.class文件。
方法2:替换client-support.jar目录中的\com\sitraka\licensing\ LicenseProperties.class文件。
破解文件:
Jprobe_v8.0.0_Crack
JProbe.Suite.v8.1.0.Cracked-FALLEN

按照说明,这似乎是个有用的东西。等我试用之后才能确定。
然而,安装过程实在太麻烦了。
体会1:插件其实是不能单独安装的。必须同时安装软件本身和插件。有消息说只用插件不需要注册码,但我尝试的结果是不注册不能用。网上找不到8.1版本的密钥,所以不建议安装8.1版本。8.0即可。
体会2:虽然User Guide里面给出了详细的使用说明,但我使用这个插件的过程还是困难无比。核心部分在于,在敲所有命令的时候,一定不能用键盘上的空格。必须把有空格的目录名复制粘贴。这一点折磨了我整个晚上。
网上给出的注册码使用过程是这样的:首先将crack中提供的jar文件复制到jprobe安装目录,然后运行console程序,将crack中的license加进去即可。

近日的工作进展:21st-25th

5月21日

写代码!
读数据流程:
1. 从文件到表,直接读入。以天为单位。保留一个最终的“目前在线”。
2. 统计用户。更新用户表。
3. 确定时间间隔,区分会话。
4. 区分行为。

5月22日

使用read(byte[])读入数据,而后使用函数byte2int()和int2ip(),int2date()等做转换。用reverse()函数将byte[]倒过来。
连接Oracle数据库,使用PreparedStatement类执行SQL语句。conn.prepareStatement一次语句可以用无限次,每次只需要重新设定?的值。
每条数据写完后addBatch(),数量攒到差不多的时候再executeBatch(),等到全都做完再commit.
PreparedStatement和Connection用完了要记得close()一下。
该好好学SQL了……虽然就那么几句,可是妙用无穷啊。
Oracle跟Java的数据类型差异:使用Timestamp和Number,放弃boolean。

5月25日

尝试AddBatch()和ExecuteBatch()。
读入100万条,每500条提交一次,所需时间为302031ms,即约5分钟。
将所有数据删除过程也为约5分钟……
此时数据库文件夹848M。删除所有100万条数据后为1.01G……由于出现了新的undo文件。
读入数据3000万条,耗时9414609ms即2.6h。每1000条提交一次。最后才commit一次。
每条0.31ms,每秒3200条。
最后一条记录时间为下午1点29分。
3.83G。还可以接受。

数据读入模块代码

import java.io.*;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.sql.*;
import oracle.jdbc.driver.*;
public class read{
Connection conn;
public void FileRead(String f) throws IOException
{
Date StartTime=new Date();
FileInputStream fin = new FileInputStream(f);
converter C=new converter();
byte[] head=new byte[20];
byte[] Bip1=new byte[4];
byte[] Bip2=new byte[4];
byte[] Bport1=new byte[2];
byte[] Bport2=new byte[2];
byte[] Bendtype=new byte[1];
byte[] Bconnecttype=new byte[1];
byte[] Bempty1=new byte[2];
byte[] Btime1=new byte[4];
byte[] Btime2=new byte[4];
byte[] Binpack=new byte[4];
byte[] Boutpack=new byte[4];
byte[] Binbyte=new byte[4];
byte[] Boutbyte=new byte[4];
byte[] Bidl=new byte[1];
byte[] Bempty2=new byte[11];
StringBuilder ip1=new StringBuilder(15);
StringBuilder ip2=new StringBuilder(15);
int port1, port2, endtype, inpack, outpack, inbyte, outbyte;
boolean connecttype,idl;
Date time1=new Date();
Date time2=new Date();
SimpleDateFormat DF=new SimpleDateFormat();
DF.applyPattern(“yyyy.MM.dd HH:mm:ss”);
fin.read(head); //文件头
long N=0; //记录条数
PreparedStatement tt;
try
{
tt=conn.prepareStatement(“INSERT INTO ORIGINDATA1 VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)”);
while(fin.read(Bip1)!=-1&&N<30000000)
{
fin.read(Bip2);
fin.read(Bport1);
fin.read(Bport2);
fin.read(Bendtype);
fin.read(Bconnecttype);
fin.read(Bempty1);
fin.read(Btime1);
fin.read(Btime2);
fin.read(Binpack);
fin.read(Boutpack);
fin.read(Binbyte);
fin.read(Boutbyte);
fin.read(Bidl);
fin.read(Bempty2);
ip1.delete(0, 15);
ip1.append(C.int2IP(C.byte2int(C.reverse(Bip1))));
ip2.delete(0, 15);
ip2.append(C.int2IP(C.byte2int(C.reverse(Bip2))));
port1=C.short2int(C.byte2short(C.reverse(Bport1)));
port2=C.short2int(C.byte2short(C.reverse(Bport2)));
endtype=(int)Bendtype[0];
connecttype=C.byte2bool(Bconnecttype);
time1=C.int2Date(C.byte2int(Btime1));
time2=C.int2Date(C.byte2int(Btime2));
inpack=C.byte2int(Binpack);
outpack=C.byte2int(Boutpack);
inbyte=C.byte2int(Binbyte);
outbyte=C.byte2int(Boutbyte);
idl=C.byte2bool(Bidl);
N++;
/*
if (N%1000>0)
{
System.out.println(N);
System.out.print(ip1);
System.out.print(” “);
System.out.print(ip2);
System.out.print(” “);
System.out.print(port1);
System.out.print(” “);
System.out.print(port2);
System.out.print(” “);
System.out.print(endtype);
System.out.print(” “);
System.out.print(connecttype);
System.out.print(” “);
System.out.print(DF.format(time1));
System.out.print(” “);
System.out.print(DF.format(time2));
System.out.print(” “);
System.out.print(inpack);
System.out.print(” “);
System.out.print(outpack);
System.out.print(” “);
System.out.print(inbyte);
System.out.print(” “);
System.out.print(outbyte);
System.out.print(” “);
System.out.print(idl);
System.out.println();
}
*/
tt.setLong(1, N);
tt.setString(2, ip1.toString());
tt.setString(3, ip2.toString());
tt.setInt(4, port1);
tt.setInt(5, port2);
tt.setInt(6, endtype);
tt.setInt(7, C.bool2int(connecttype));
tt.setTimestamp(8, new java.sql.Timestamp(time1.getTime()));
tt.setTimestamp(9, new java.sql.Timestamp(time2.getTime()));
tt.setLong(10, inpack);
tt.setLong(11, outpack);
tt.setLong(12, inbyte);
tt.setLong(13, outbyte);
tt.setInt(14, C.bool2int(idl));
tt.addBatch();
if(N%1000==0)
{
tt.executeBatch();
System.out.print(N);
System.out.print(”  “);
System.out.println(new Date());
}
}
tt.executeBatch();
conn.commit();
System.out.print(N);
System.out.println(new Date());
tt.close();
conn.close();
fin.close();
Date EndTime=new Date();
System.out.println(EndTime.getTime()-StartTime.getTime());
}
catch (SQLException e)
{
System.out.println(e);
}
}
public void read(){}
public void initialize() throws Exception
{
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
conn=DriverManager.getConnection(“jdbc:oracle:thin:@192.168.75.128:1521:flow”,”sysman”,”********”);
conn.setAutoCommit(false);
System.out.println(“Connected!!”);
}
public void closeDB() throws Exception
{
conn.close();
conn=null;
}
public static void main(String[] args)
{
String Fi=”E:\\log\\20090408\\NetFlow20090408_connect.log”;
read r=new read();
try
{
r.initialize();
}
catch(Exception e)
{System.out.println(e);}
try
{
r.FileRead(Fi);
}
catch(IOException e)
{System.out.println(e);}
try
{
r.closeDB();
}
catch(Exception e)
{System.out.println(e);}
}
}

长征:搞定评论回复邮件通知

前后历时数日,尝试无数种办法,直至现在。
当我终于把邮件通知搞定的时候,我只想高呼一声:贼!

在陕西话里,贼更像是当时左传上的用法,“宣公骤谏,公患之,使鉏贼之。”意思是破坏、毁灭的意思。但到如今,在口语中更多的倾向于其他地方的“日”或“干”(不雅)。例如陕西球场上大叫的“额贼”基本上就是“我日”的意思。
——百度百科:贼 http://baike.baidu.com/view/229510.htm

堪称我自使用wordpress以来面临的最棘手问题。所幸终究我还是把它解决了,而且是在明白问题所在的情况下解决的。
起因是这样的:在我使用了thread comments许久之后,我才开始意识到好像插件里的“有回复时用邮件通知我”好像没起到作用,我白白回复那么多人,可他们好像都没看到我的回复一样。于是我自己发了个test回复,想看看到底有没有邮件提醒这个功能。
果然没有。
没有就没有吧,我就去wordpress.org.cn找答案。果然有人遇到跟我一样的问题,而且似乎一模一样:那人也是用了thread comment之后发现没有邮件提醒,然后解决了这个问题。真完美,于是我就照着他说的做。
http://www.life-studio.cn/configure-smtp.html
按作者所说的,我遇到的问题是由于我用的服务器是windows系统,没有像linux主机一样提供mail()函数,因此发不出邮件。解决方法也很明确:既然自己的服务器发不出邮件,那么我们可以用其他的服务器发。使用邮件服务商的smtp服务就可以了。
作者说经他测试,常用的解决这个问题的插件中,只有magic mailer和configure SMTP是可以跟thread comment兼容的。其中前者又出现了乱码问题,所以他强烈推荐configure SMTP。
我欣然下载安装之,然后照着说明设好了gmail邮箱。发了个测试邮件。
没收到。
一点小挫折,算不上什么。我搜索使用这个插件可能遇到的种种问题,果然有很多人遇到了问题,然而各自不同。有人说要把用户名称填对,有人说要记得写邮箱后缀,有的人说要把某个框跟某个框内容填成一样,有人说用qq邮箱比较好,还有人推荐163。gmail自己则说他们提供了好几个端口,用户们可以挨个试试看……
我都试了。
还是不行。
我有点草鸡了。

山东胶东半岛地区的方言,也可说(草计),意思就是不行了,受不了了。例如,某人干一个活又脏又累,他可以说,这个活可草鸡死我了。
——百度百科:草鸡 http://baike.baidu.com/view/414026.htm

好吧,反正不能一棵树上吊死,还有那么多其他的插件呢。
我又试了Magic Mailer,包括使用它的各种可能性如qq邮箱或25端口之类。全都不行。
我崩溃了。这是第一日。
过了二十四小时之后我才认为自己足够平静到可以继续解决这个问题。这次我试了剩余的可能的插件,包括WP-mail-SMTP,Swift SMTP,还有从某个博客上找来的博主自己写的山寨SMTP插件。
它们统统不顶用。
不过WP-mail-SMTP还是起了作用,它告诉了我到底问题出在哪里。它说:

Unable to find the socket transport “ssl” – did you forget to enable it when you configured PHP?

并且还给出了发送邮件的整个过程,告诉我问题就出在ssl这一步上。
我用上面那句错误信息做搜索,又搜到一大堆东西。主要的意思都是说,我的主机可能没有开启ssl,需要把php配置一下。具体而言,要把php.ini里的某一句前面的“;”去掉,然后把几个什么文件放到什么地方,重启服务器即可。
就像这样 http://www.himagic.cn/index.php/archives/127.html
我登陆远程桌面,照着说明做了,然后又在新的环境条件下依次尝试了那几个插件。
全部无效。
我找了个php探针,它告诉我我的主机依然不支持ssl。
我再次崩溃。这是第二日。
又过了许久,我开始了我的第三次尝试。
要沉静,要思维清晰,不要心急。我开始寻找关于ssl的详细知识,想明白到底什么是ssl,它的原理是怎么样的。
网上给出了各种安装ssl的方法,大多很复杂,完全不想前面说的去掉一个逗号那么容易。同时有些人指出有的版本的apache就是不支持ssl的。我怀疑我遇到的就是这种情况。
更改服务器的代价太大,那么应该还有另一种可能,就是不使用ssl。
似乎有的邮件服务器可以支持不使用ssl发送邮件,但是怎么确定呢?我在试插件的时候已经试过了各种可能,难道要我从头再试一遍哪个服务商的哪个端口支持不用ssl?我去邮箱的设置页面找,他们并没有提供关于端口的详细信息。
可我还是想到了另外的办法,我打开了outlook express。
其实我从来不用这个软件的,可是为了测试一下各个邮件服务商到底支持什么样的SMTP服务,我总得自己试一试。
Gmail,仅支持SSL登录。
qqMail,仅支持SSL登录。
126邮箱,登录不能。
163邮箱,仅支持非SSL登录!!!
我把那几个插件翻出来,印象里好像有哪个可以选择不使用ssl加密。Magic Mail就行。而且据说可以跟Thread comment兼容。
我把Magic Mail设置为163邮箱,不使用SSL,发了个测试邮件。
成功!!!!
我继续测试评论回复邮件功能,证实只有前台回复才会有提醒邮件,后台回复就不可以。
至此,长征终于胜利。
教训:
1.做事情不能只按照说明书一步一步地走,遇到说明书上没写的状况就完蛋了。要明白事情运行的原理。
2.要明白达到成功的几种可能路径,同时看清楚哪些条件是自己可以改变的,哪些是自己不能改变的,然后改变那些可改变的,从而满足成功的条件。
p.s. 没遇到什么中文乱码问题。

RSS烧制日记

前几天我正在折腾RSS订阅,在主页上加了订阅到几个常用阅读器的链接。可是这几个网站提供的图标各自不同,排在一起显得很乱。
后来我又撞到feedsky去,很高兴地发现这里还提供订阅到各个服务器的链接,而且图标很统一。于是我很开心地在feedsky烧制了一个RSS,然后把链接放到主页去。接下来,我点了那个“订阅到九点”的按钮做试验。
于是,我的豆瓣九点里出现了第二个“戈城的新城区”。
我懵了一下,又试抓虾,一样的。我开始犯晕,过了一阵子才明白过来,哦,原来所谓烧制RSS是重新做了一个永久RSS,然后订阅这个新的RSS!于是此前已经订阅我博客的那几个人跟往后订阅的人订的就不是同一个RSS源了,而是同步更新的两个源……我可不喜欢这种感觉。我的博客开张虽然不久,订户也不多,可google加抓虾加鲜果算在一起也有差不多十个人了,我不乐意看到他们在许久之后发现自己仍然是这个博客仅有的几个订户之一。
于是权衡利弊之下,我把feedsky的那个feed删掉了,我主页上那些链接也一并删掉,还是用原始的RSS。可是我做了件傻事,我把原来那些RSS订阅的代码替换掉了,没有备份……
于是我对RSS烧制失去了兴趣。
……
过了几天。
我又想起来自己的订阅按钮,于是研究了下它的语法,发现很简单啊。然后我把feedsky提供的那些很整齐的小图标存了下来又传到我服务器上,给每个按钮写了这样的代码:
<a title=”订阅到豆瓣九点” href=”http://9.douban.com/reader/subscribe?url=www.rexcel.us” target=”_blank”><img src=”http://www.rexcel.us/wp-content/uploads/2009/05/icon_subshot02_douban.gif” alt=”” /></a>
后来我又想,其实我还是很想知道自己的博客有多少人订阅并且把这个数字让人知道的。而且把各个阅读器的订阅数加起来之后那个数字会比较好看。我心想要是有个办法能让我的原始RSS地址跟烧制后的一样就好了。
于是我就去Wordpress.org.cn寻找这样的方法。找到的方法说可以把自己的域名绑定到feedburner上,在这里。这篇文章提到CNAME方式的绑定在国内不能用,但是仍然有办法突破封锁……我承认我没看懂这篇东西在说什么。
但是我想,也许我该先注册feedburner,对它有些了解之后可能就看得懂了。所以我上feedburner,才很无知地发现原来它是google提供的一项服务……于是我放心了。
在feedburner晃了一圈,没搞明白多少事情,我又回到Wordpress.org.cn,搜索feedburner。这时候我的救星来了,它就是Feedsmith。

插件说明:
这个插件可以探测到所有进入你的博客的feed地址(例如:http://www.creativead.cn/feed/ 或者http://www.creativead.cn/wp-rss2.php),并且将它们全部转向到你的FeedBurner feed页面。同时,你还可以将你的博客评论的feed地址也这样处理。
注意:适合wordpress 1.5版到wordpress 2.5版使用!
安装方法:
1、下载FeedBurner FeedSmith插件
地址:http://www.feedburner.com/fb/pro … mith_plugin_2.3.zip
2009-2-14 11:41
2、解压缩,请取出feedburner_feedsmith_plugin_2.3文件夹下的FeedBurner_FeedSmith_Plugin.php文件
3、将FeedBurner_FeedSmith_Plugin.php上传到wordpress博客插件目录wp-content/plugins/ 下
4、登录后台,激活FeedBurner FeedSmith插件。
5、在后台”设置”菜单下找到”FeedBurner”.在第一个方框中填写已经在google feedburner 上烧录好的博客feed(例如:http://feeds2.feedburner.com/snowdream2009),在第二个方框中填写烧录好的博客评论feed(例如:http://feeds2.feedburner.com/snowdreamcomments),点击”save”进行保存。

我下载了FeedSmith,然后点击我博客的原始RSS。它跳到Feedburner去了。我狠开心。
订阅也没有问题。无缝连接。

博客图标更新

戈城的新城区图标一直都是默认图标,我看那个ie7图标看烦了。于是,我把它改了。
首先是制作图标。我前两天换博客模版时刚做了几个新banner,于是把里面的字抠出来,选了一个“城”字作为图标。在fireworks里面新建一个16*16像素的图片,然后把那个字粘进去,调一调尺寸。
我做了两种配色,一种白底蓝字,一种蓝底白字。我喜欢那个蓝底白字的。
faviconcaneauja
favicon
可是图标不能是fireworks默认的png格式,得是ico格式。fireworks没这个功能,我又懒得下载那些转换软件。于是我上网去搜,搜到一个好用的小网站。
www.convertico.com
把自己的png文件上传,或者提交一个线上的png文件,它就会生成一个相应的ico文件下载。
然后我把ico文件传上服务器,把地址复制下来。
接下来我编辑了我的主题,在header.php里面,我在<head>标签里面加入了两句:
<link rel=”shortcut icon” href=”http://www.rexcel.us/wp-content/uploads/2009/05/favicon.ico” />
<link rel=”icon” href=”http://www.rexcel.us/wp-content/uploads/2009/05/favicon.ico” />
ok。一切搞定。于是我博客的图标就变成可爱的蓝底小白字了。
icon

谷歌地图震撼升级

今天逛豆瓣的时候,偶然看到google小组的新话题,内容如下:

地图和卫星图片契合了

Dylen 2009-05-11 15:08:21  来自: Dylen(视野愈阔,断言愈少。)

  http://ditu.google.cn/
  
  终于。。。
  
  告别反恐时代。。。

我立刻去看google地图,第一个发现是字体变好看了。看起来像微软雅黑,但是细看下来在细节又有所不同。
然后我去点卫星图,世界一下子不同了。
map
谷歌地图的卫星图上出现了标注!地图上的所有标注都在卫星图上得到了体现,从地标到道路,一切都对上了。
我把地图放大到西安交大,然后囧然发现……
map2
我的神啊,连交大里面的什么思源路星火路都有!这工作量,太吓人了!
我又查看其他的城市,发现基本上县级以上城市的主要道路都会被标注出来。国道省道自不必说。但这个也还是存在地域性差异的……好比说山东的基本上是个县都会有详细地图,而类似于陕西省宁陕县这样的地方就只有一条国道210通过去。
map3
而后,我把地图放大到全球范围,才发现原来这个地图是用各国的母语显示的,在中国显示中文,在俄罗斯就显示俄语了。
这个新功能……真是牛到家了。从此看谷歌卫星地图不必再一条街一条街地数,因为卫星图已经跟地图合二为一了!

人工神经网络算法应用

同样是廖貅武教授的软计算方法课程作业。两个小作业之一。考虑到上一个遗传算法的作业做得实在太没有含量了,我决定把这个人工神经网络做得原创性高一点。
于是,OK,我就原创一个题目吧。
问题:
    给定一个超越函数在某些采样点的取值,使用人工神经网络模拟出这个超越函数。以Matlab自带的函数peaks()为例。peaks()在[0,30]的图像如下:

数据:
    产生一个数组r,结构为3*300,内容为从peaks()上随机采样的300个点的x,y,z坐标。我将把x,y坐标作为输入变量,z坐标作为输出变量构建一个BP人工神经网络。结构如下:
 
工具:
    Matlab 6.5+神经网络工具箱。
    这里出现了我遇到的最大教训。教训是:装软件一定要装完整版。我开始写了个ANN的程序,结果发现运行不了,提示函数未知。我以为要加载个什么工具包,于是在整个网络上搜,搜了两小时也没搜出来,似乎所有人都直接用了,根本不存在什么加载或调用的问题。然后,我才认识到我的matlab是个不完整版,没有NN工具包……我愤而下载了一个Matlab7,决意把这可恶的6.5彻底抛弃。然后……花了一小时下载的M7居然不能装!原因未知!我只好又花了半小时下了一个matlab6.5的完整版,这才把问题解决。
细节不再赘述,直接上程序。
 
train.m:训练函数
load r.mat;
[P,minp,maxp,T,mint,maxt]=premnmx(r(1:2,:),r(3,:));
 
%建立网络
S=6; %隐含神经元数
L=1; %输出神经元数
net=newff([minp,maxp],[S,L],{‘logsig’,’tansig’,’purelin’},’traincgb’,’learngdm’);
 
%初始化
net=init(net);
 
%网络训练
net.trainParam.show=20;%设置训练显示间隔次数
net.trainParam.epochs=600;%设置最大训练循环次数
net.trainParam.goal=0.0001;%设置性能目标值
net.trainParam.lr=0.1;%设置学习系数
[net,tr]=train(net,P,T);%网络训练
 
test.m:测试函数
te=[0 0];
for i=0:30;
for j=0:30;
tt=[i j];
te=[te;tt];
end;
end;
fi=sim(net,te’);
aa=zeros(30,30);
s=1;
for i=1:31;
for j=1:31;
aa(i,j)=fi(s);
s=s+1;
end;
end;
mesh(aa);
 
运算结果:
 
训练效果

绘制出神经网络所模拟的函数图像:

 
    经过多次计算,发现每次计算绘出的函数图样差异较大,同时与peaks函数本身也有较大的差异。
    运用人工神经网络算法对此超越函数的模拟效果较差,可能是由于多个原因。首先,对函数值的随机采样可能没有体现函数的全部特征;其次,神经网络结构较为简单,可能难以模拟一个如此复杂的函数;第三,输入变量较少,可能不适合使用神经网络进行计算。
 
=====================郁闷的分割线======================
就这样,我发现人工神经网络根本模拟不出这个复杂的peaks函数……可能是这神经网络的智商太低,也可能是我的智商问题……不过,反正是交作业,这也无所谓。

博客故障记

那事情是前天发生的。我从没想到那么一个小小的失误,居然会造成这么严重的后果。
事件发生的具体时间是2009年4月25日14点34分50秒。有文件创建时间为证。那时我正在试验各种显示最新评论的插件,先尝试了recent-comments,然而这玩意儿在我博客首页上显示MySQL语法错误。于是我又下载了get-recent-comments打算试试看。
安装get-recent-comments的时候我偷了个懒,没有把Zip文件解压后通过ftp上传,而是直接用Wordpress的安装插件功能直接通过页面上传的方式安装了这个插件。
然后,一切都完蛋了。
当我刷新博客页面的时候,我觉得好笑。怎么每个页面的上方都出现了一大堆代码?我细细地读,发现是一个Changelog,是get-recent-comments这个插件的更新记录。无论是博客主页还是文章页面,甚至管理页面都是如此,在博客正文的最前面,长达两屏的Changelog密密麻麻地排满了屏幕,仿佛我家房顶上厚厚地盖了一层两米高的恶心的蝗虫尸体。
于是我就把这个插件禁用了。
无效。
我通过ftp把插件目录删了。
无效。
我崩溃了。我向那几个管理服务器的家伙求助,可他们都不在线。这时angie扯着我出去逛街,我一边走路一边心乱如麻。我试着登录Wap版,发现手机屏幕上也是那些恶心的蝗虫尸体。
逛街回来之后我向管理员要了远程桌面密码,可是家里的网通线路根本连不上远程桌面;我通过QQ的远程协助连到angie的电脑,然后从angie那里连接服务器的远程桌面,然后……发现管理员给的密码是错的。我心中大骂猪77,可那家伙又不在线了。我一行一行地研究模板代码,想搞明白什么原因能导致这种诡异的事件,居然页面与后台通杀!折腾一晚,无果。我只好写了一个”博客故障,抱歉”的文档,命名为index.html,扔到服务器根目录下,这样别人就不会看到那些恶心的蝗虫尸体,而只是这行字了。
我似乎从未觉得周末如此漫长,一心等着周一到学校去彻底解决问题。期间收到ephe的回复说我页面上方changelog的问题……心中更加纠结。
今天下午我终于来到工作室,要到了正确的远程桌面密码,连接远程桌面,在整个博客目录里搜索内文有”ChangeLog”的所有文件。然后,我在/wp-content/plugins/目录下发现了那个changelog.html。这里还有get-recent-comments的其他文件。
……
我把它们都删了。
打开博客主页的时候,我开心地发现蝗虫尸体一扫而光。我转到后台的插件管理,它告诉我changelog.html插件已被禁用,因为文件目录不存在。
原来如此!自动安装功能把这个插件直接安装到了plugins目录,于是wordpress就把changelog.html当作了一个插件。于是这个混账插件在所有页面都显示为页面最上方的一堆死蝗虫。
结论或教训:
1.安插件的时候要小心。
2.远程桌面是无敌的,ftp是白痴的。