<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>4G spaces &#187; Python</title>
	<atom:link href="http://blog.youxu.info/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.youxu.info</link>
	<description>I am Eric Xu, a Googler.</description>
	<lastBuildDate>Fri, 03 Feb 2012 06:31:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>完全用命令行工作-4: 苹果图形界面脚本化</title>
		<link>http://blog.youxu.info/2008/10/19/macos-and-command-line-script/</link>
		<comments>http://blog.youxu.info/2008/10/19/macos-and-command-line-script/#comments</comments>
		<pubDate>Sun, 19 Oct 2008 19:26:06 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[CompSci]]></category>
		<category><![CDATA[Cool Stuff]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[macos]]></category>

		<guid isPermaLink="false">http://blog.youxu.info/?p=666</guid>
		<description><![CDATA[我用苹果 Mac OS X 两年了, 越用越觉得, 其他操作系统要从苹果的 Mac OS X 上学习很多东西. 特别是图形界面的统一的脚本化接口, 我认为这对未来的操作系统是一个很好的启示, 也是完全用命令行... ]]></description>
			<content:encoded><![CDATA[<p>我用苹果 Mac OS X 两年了, 越用越觉得, 其他操作系统要从苹果的 Mac OS X 上学习很多东西. 特别是图形界面的统一的脚本化接口, 我认为这对未来的操作系统是一个很好的启示, 也是完全用命令行工作哲学在图形界面时代的一个不可缺少的部分.</p>
<p><img class="alignleft size-medium wp-image-669" title="textedit_icon" src="http://blog.youxu.info/wp-content/uploads/2008/10/textedit_icon-300x300.png" alt="" width="210" height="210" align="left" /></p>
<p>起因是最近我在写一系列的中文文章, 因为几乎没有数学公式, 而我又喜欢纯文本的工作方式, 因此在排版上我选择了<a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>. 一般来说, 英文文本我都是直接在 vim 下工作. 可是苹果下的 vim 对中文的支持不是想像的那么好, 至少中文输入法打出来的常常有乱码. 名动天下的 <a href="http://macromates.com/">TextMate</a> 固然好, 显示中文却只有半个字那么宽, 看上去很不舒服. 其他的编辑器要么收费, 要么嫌大, 要么不顺手, 因此落到最后还是用了苹果的 TextEdit.</p>
<p>但是写技术文章的人都知道, 写文章不仅是打字这么简单. 特别是技术文章, 常常需要离开编辑环境跑脚本, 查Google, 看 wiki. (我不知道别人是不是这样, 至少我为了写出质量较好的文章, 写的时候也要做很多功课). 特别是因为我在用 reStructuredText, 一个最基本的需求就是处理当前文本生成 HTML/LaTeX 然后预览. 这些需求, 在 VIM 和 TextMate 中都是原生支持的, 很简单能做到. 但是在 TextEdit 这样的软件中, 乍一看, 毫无办法. 所幸的是, UNIX 家族的操作系统, 特别是苹果, 秉承了 简单的事情要有简单的解法, 复杂的事情要有可能的解法 这样的设计思路, 提供了不止一条解决问题的方法. 因为苹果设计了一个叫做&#8221;脚本化应用程序&#8221;的东西, 使得这些任务可以很简单的完成. 我研究了几天, 学到了一些东西, 拿出来和大家分享.</p>
<p>1. 最常常被忽略的菜单栏, Service 菜单.</p>
<p>用具体的例子来说可能更加简单. 用 Gmail 的各位都知道, 如果邮件里面有 90081243455 这样的数字串, 或者有 北京是西城区XX路YY号 这样的地址, Gmail 就很贴心的显示出 &#8220;使用 Google 追踪快递包裹&#8221; 或者 &#8220;使用地图查看地址&#8221; 这样的链接. 也就是说, Gmail 会识别出这些特定的样式, 然后给你一个上下文相关的(也就是说, 和你内容相关的) 服务. 这样的服务贴心舒适, 相信不少人都很喜欢. 一般我们把这个叫做上下文相关的服务.</p>
<p><a href="http://blog.youxu.info/wp-content/uploads/2008/10/ubiquity_side.png"><img class="alignright size-medium wp-image-670" title="ubiquity_side" src="http://blog.youxu.info/wp-content/uploads/2008/10/ubiquity_side.png" alt="" width="150" height="213" align="right" /></a>再说 Firefox. 前不久 Firefox 出了一个很贴心的小插件, 叫做 <a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a>, 我在 Firefox 下几乎离不开它: 选中任何一行地址, 只需要敲几个键, 就可以查 Google Map. 选中任何一个名词, 可以立即查 Wikipedia, 等等. 一般我们把也把这个叫做基于选定的服务.</p>
<p>苹果上的 Service 菜单, 就是这样的一个基于上下文相关和基于选定的服务. 举个最简单的例子, 如果你的机器上装有 Skype, 然后你选中了一串电话号码, 这时候你可以到 Service 菜单中选择 Skype -&gt; Call this number. Skype 就会自动拨打这个电话. 或者选中一个单词, Service 菜单中就会自动出现: Look up in the Dictionary. 选中它以后, 你机器上的字典就会跳出来, 把单词的释义呈现给你. 所有的这一切, 都是基于苹果的一个叫做 System Service 的框架. 简单的说, 每个应用程序告诉系统: 在什么情况下, 你给我什么信息, 就可以让我做什么事情. 这样, 在选定的上下文符合条件的时候, 你就可以在菜单中选择这个服务. 这个东西方便无比. 比如说, 常常老板在邮件里面写: 你这周做啥啥. 我就可以选中整行句子, 按下 ⇧⌘ Y. 这样整行句子就被纪录到 Stickies 里面去了, 相当于随时写下一个便签.</p>
<p>现有的菜单栏固然好, 但是自己编写的更加好玩. 所幸的是, 你不需要会苹果的生涩的 Obj-C 才能编写菜单. 有一个强大的工具, 叫做 <a href="http://wafflesoftware.net/thisservice/">ThisService</a>, 能够把 Ruby, Python, Applescript 和 shell 脚本都包装成 Services. 比如说我昨天就花了一分钟写了一个很简单的叫做 Translate 的脚本, 通过 Python 提交文本给 Google Translate, 返回中文. 在阅读有很多不认识的单词的新闻文章时候, 只要选中段落, 选择这个 Translate. 一个翻译成中文的窗口就出现了.  在这个软件的帮助下, 任何脚本都能点一下鼠标就变成一个服务: 具体我就不一一详述了.</p>
<p>总的来说, 我们可以注意到, 在日常使用计算机的时候, 一个应用程序中的一些内容(文本或者图像),  往往要作为另外一个程序的输入, 交给另外一个程序处理. 比如选中的单词查字典, 选中的地址查阅地图, 和选中的电话号码拨打, 选中的句子翻译等等, 这些需求都是存在的. Windows 家族解决问题的方法, 是通过程序切换和剪切板. 而苹果就是通过统一的接口来完成的, 思想和UNIX管道是非常相似一脉相承的 (当然, windows 家族从来就没有 UNIX 家族管道这个思想, 所以也就想不出统一接口这样的设计了).</p>
<p>在苹果下, 统一脚本接口可以用来处理像 Service 这样的程序之间通信的问题, 这个是 windows 家族从来没有想过的. 同时, 据我个人经验, 这个思想在 Linux/X11 家族也没有全部实现. 在 Linux 命令行下, 我们都知道, 不同的小工具之间是正交的, 一个程序的输出是一个程序的输入, 这个 UNIX 哲学长盛不衰. 直到今天, 正常的 Linux/UNIX 用户也会天天用管道做程序之间的通信. 可是在图形界面出现后, 这样的好传统在 X11 系统中似乎没有被继承. 比如, 不能选中一段文字直接送给 wc 计算字数. 究其原因, 是因为图形界面再也没有明显的输入输出这个概念了. 字符串和图像变成了要在程序之间传送的基本单位. 在这种情况下, 就需要不仅仅以文件为基本单位, 而是以被选中的那些字符串, 句子, 链接, 图片等为基本单位的通信. 在这个层面上, 苹果的确先行一步. (当然 Emacs VIM 等等也是可以通信和调用外部程序的, 但是毕竟不是整个系统都能这样).</p>
<p>2. 史上最简单的语言, AppleScript.</p>
<p>故老相传, 当年 Knuth 大神访问苹果, 总裁 乔布斯 同学发挥爱吹牛的光荣传统, 说: 高教授, 您来了. 我特别崇拜你, 您的书我都读过. 各位读者都知道, 要是Jobs 真的把高教授的书都读过, 全世界大学计算机系99%的教授基本上都要自杀让位给Jobs. 所以, 高爷子知道他吹牛皮. 以下的故事分两个版本, 第一个版本是硅谷的版本, 是高爷子当即就说: 斯蒂夫同学, 你又扯淡忽悠了. 第二个版本是我的版本: 说高爷子一听, 也不生气, 心想, 你我共同作为硅谷两个最懂字体设计的搞IT的, 我也不好得罪你, 且问你一道简单的问题, 看你读了我哪几本书. 于是高爷子眼珠一转, 题上心来, 问到: 乔布斯同学, 请问世界上最简单的编程语言是啥子呢? 乔布斯是个不懂技术的主. 想起当年和 Woz 合作的时候搞的东西叫做 BASIC, 听名字就觉得简单, 于是说道: 乃是 BASIC. 高爷爷说, 还有比这个更简单的么. (话说高爷爷心想, 我手里握着 TeX, Metafont, MIX, Literate Programming, CWEB 等几张王牌, 我就不信你说不出一个搭不上边的). 乔布斯同学哪能体会到高爷爷的良苦用心, 他又不会编程, 于是就杜撰到: 我们公司最近正在开发世界上最简单的一个语言: 叫做苹果脚本(AppleScript). 高爷爷一听就知道又是吹牛, 于是立即回复: 斯蒂夫, 你又扯淡忽悠了. 斯蒂夫同学哪服软, 于是要求开发部门开发一个连他都懂怎么用的语言. 于是 AppleScript 就被捣鼓出来了.<br />
(以上故事纯属扯淡忽悠)</p>
<p>话说AppleScript 有多简单呢? 就和说话一样简单. 我曾经也写过介绍. 再这里再给一个例子:</p>
<p><code><br />
tell application "TextEdit"<br />
set filename to name of document 1<br />
print filename<br />
end tell<br />
</code></p>
<p>看, 明明就是英语嘛! 这么平铺直叙几乎没有语法的编程语言, 真的是世界上最简单的编程语言唉.</p>
<p>别看这个语言简单, 威力可不小. Mac 上几乎所有的应用程序, 都能够用这个语言去控制, 特别是 iTunes 甚至还有一个<a href="http://dougscripts.com/itunes/">专门的网站</a>, 专门就让你下载千奇百怪的控制脚本.</p>
<p>Applescript 还有两个好处: 1. 他是苹果原生支持的, 可以直接编译成苹果的应用程序来用. 因此, 简单的任务处理都可以用这个语言. 比如我们上面说的做成 Service 的, 也可以用 Applescript 来实现. 2. 他能够和其他应用程序交互. 其实在苹果系统中, 在脚本桥技术(Script Bridging) 出现之后, 理论上C/Javascript/Python/Ruby 都是可以和应用程序交互的. 可是AppleScript 的支持更加好, 更加直接. 比如取当前播放的iTunes乐曲名字, 可以用<br />
AppleScript:</p>
<p><code>tell application "iTunes" to get the name of the current track</code></p>
<p>也可以用 Python</p>
<p><code>from Foundation import *<br />
from ScriptingBridge import *<br />
iTunes = SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes")<br />
print iTunes.currentTrack().name()</code></p>
<p>显然 Python 要显得笨重一些.</p>
<p>同时, AppleScript 也是苹果中小机器人 Otto  <a href="http://blog.youxu.info/wp-content/uploads/2008/10/automator_icon.png"><img class="alignright size-medium wp-image-667" title="automator_icon" src="http://blog.youxu.info/wp-content/uploads/2008/10/automator_icon-300x300.png" alt="" width="144" height="144" align="right" /></a>的底层技术, 因此在整个系统中发挥了基础性的作用. 虽然学习 AppleScript 显得很偏很不入流, 但是在苹果上做一些小任务有时候还是用得着的. 比如说我的让 TextEdit 支持 ⇧⌘ R 自动编译的例子, 就是先写了一串脚本, 取当前文件名, 然后使用 do shell script 这个指令调用 make. 这样, 调用这个脚本, 就可以完成自动编译. 用快捷键来调用脚本, 有两种方式, 一种是通过把脚本拷贝到应用程序的脚本目录并且添加一个菜单项. 另一种是用 QuickSilver 来帮忙了. 第一种方法应该最简单, 但是我没有尝试成功, 有兴趣的读者可以读<a href="http://oreilly.com/pub/a/mac/2007/06/08/hit-and-run-launching-applescripts-with-keyboard-shortcuts.html">这篇文章</a>.</p>
<p>3. QuickSilver</p>
<p><a href="http://blog.youxu.info/wp-content/uploads/2008/10/quicksilver.png"><img class="alignleft size-medium wp-image-668" title="quicksilver" src="http://blog.youxu.info/wp-content/uploads/2008/10/quicksilver.png" alt="" width="128" height="128" align="left" /></a>我曾经间或的提到过 QuickSilver. 刚开始我并不能体会到他的魔力, 直到最近在玩脚本控制的时候才发现. 简单的说, QuickSilver 就是能让你用键盘控制程序的程序. 或者说, QuickSilver 就是键盘命令中枢. 比如说播放音乐, 只要一键激活 QuickSilver, 再打一下 play (有时都不要打全), 回车. iTunes 就放起音乐了. 上面我们说的任何控制系统的脚本, 都能够被 QuickSilver 控制. 我在拔掉你的鼠标一文中也提到, &#8220;你要是苹果用户又不用QuickSilver或命令行, 那你是把苹果当Windows用&#8221;.</p>
<p>QuickSilver 作为应用程序快速启动的功能大家想必都很熟悉. 控制 iTunes 大家也得心应手. 我就介绍一个被大家忽略的功能: 设置上下文相关的快捷键. 传统上, 快捷键是被应用程序定死的. 即使你写了一个扩展应用程序的脚本, 你也得点点鼠标去调用, 而不能设置键盘快捷键去调用. 解决的方法有三个, 第一个是我在第一部分讲的, 包装成一个 Service. 这样的好处是可以包装出一个快捷键, 坏处是这个Service 是全局都有用的, 不管你在哪个应用程序里面, 这个 service 都能用. 第二种是我在第二部分提到的我没有尝试成功的, 即<a href="http://oreilly.com/pub/a/mac/2007/06/08/hit-and-run-launching-applescripts-with-keyboard-shortcuts.html">添加一个菜单项目</a>的方法. 第三个就是采用 QuickSilver 的 Trigger 功能了. QS 用户可以使用 ⌘&#8217; 调出 trigger, 然后添加一个 Custom Trigger, 把目标指向自己写好的一个 AppleScript, 给这个 trigger 分配一个快捷键, 并且把使用的范围 scope 限定在一些应用程序中. 这样, 不费任何功夫, 只写一个简单的脚本, 您就可以在你的计算机上把你的 TextEdit 也改造成一个功能强大的编辑器了.</p>
<p>结语: 如我在<a href="http://blog.youxu.info/2008/09/04/unplug-your-mouse/">拔掉你的鼠标</a>一文中说的, 完全使用键盘能强迫人使用高效简洁和正确的工具. 随着图形界面和多媒体的出现, 鼠标的反而成了一个最常见的动作. 其实认真分析鼠标点选操作就发现, 无非是两种: 一种是用鼠标选择内容, 准备用一定的工具和程序处理这个内容, 还有一种是鼠标选择操作. 前者对内容的选择, 鼠标是高效的. 而后者对操作的选择, 鼠标是低效的 (因为键盘快捷键和命令行更加高效). 因此, 如果我们想要高效的工作, 就要避免后一种操作, 并且进一步解放前者.</p>
<p>对后一种的避免很简单: 拔掉鼠标, 强迫用键盘. 对前者的解放, 随着各种各样如 Service, Ubiquity 以及上下文敏感程序的兴起, 使得我们不需要在不同的程序之间拷贝来拷贝去, 而是直接通过程序之间的标准接口通信, 使得我们甚至不需要切换程序. 所有的都应该这些基于命令行和后台来完成, 而不是通过分散注意力切换程序来完成. 这些新的工具, 更加符合一个高效能的现代人的需求, 更加能够提升你的效率. 当然, 决定做事的效率的不仅仅是工具, 因此, 不要迷恋这些工具. 为了获得 1% 效率的提升, 而过于强调工具的各种淫巧, 反而降低效率. (警告: 这些工具都是非常迷人的, 很容易一用就爱上它们. 记住, 效率是最好的判断标准 :).</p>
<p>附 &#8220;完全用命令行工作系列&#8221; 文章一共五篇, 写了也不少了, 有些工具我一笔带过, 有些我花了几句话讲了一下. 基本上我介绍到的提到的, 都是我自己天天用的, 也是我认为非常有用的. 我写作的时候也都是带着 &#8220;Smart and Get Things Done&#8221; 的哲学, 只介绍干净的设计良好的软件. 各位想实践 GTD 的读者可以自行选择趁手工具. 有更多的 GTD 的完全用 键盘/命令行 工作的软件, 也不妨向我推荐.</p>
<p><a href="http://blog.youxu.info/2008/09/16/cli/">完全用命令行工作-3: 常用工具</a></p>
<p><a href="http://blog.youxu.info/2008/09/10/gtd-by-cli/">完全用命令行工作-2: 常用软件</a></p>
<p><a href="http://blog.youxu.info/2008/09/04/unplug-your-mouse/">完全用命令行工作-1: 拔掉你的鼠标</a></p>
<p><a href="http://blog.youxu.info/2008/03/20/some-handy-scripts/">完全用命令行工作: 几条趁手语句</a></p>
<div id="google_plus_one"><g:plusone></g:plusone></div>]]></content:encoded>
			<wfw:commentRss>http://blog.youxu.info/2008/10/19/macos-and-command-line-script/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Pyipopt, Python marries with Ipopt</title>
		<link>http://blog.youxu.info/2008/05/10/pyipopt-python-marries-with-ipopt/</link>
		<comments>http://blog.youxu.info/2008/05/10/pyipopt-python-marries-with-ipopt/#comments</comments>
		<pubDate>Sat, 10 May 2008 19:17:35 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Cool Stuff]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Science]]></category>

		<guid isPermaLink="false">http://blog.youxu.info/2008/05/10/pyipopt-python-marries-with-ipopt/</guid>
		<description><![CDATA[Ipopt is a leading nonlinear optimization tool. There are a bunch of interfaces, e.g. C/C++ standard interfaces, Java and MATLAB interface, FORTRAN interface for programmers.  However, no existing interface to python was presented. I started to connect ... ]]></description>
			<content:encoded><![CDATA[<p><a href="https://projects.coin-or.org/Ipopt">Ipopt</a> is a leading nonlinear optimization tool. There are a bunch of interfaces, e.g. <a href="http://www.coin-or.org/Ipopt/documentation/node27.html">C/C++ standard interfaces</a>, <a href="https://projects.coin-or.org/Ipopt/browser/trunk/Ipopt/contrib?rev=1122">Java and MATLAB interface</a>, <a href="http://www.coin-or.org/Ipopt/ipopt-fortran.html">FORTRAN interface</a> for programmers.  However, no existing interface to python was presented. I started to connect ipopt with python two months ago inspired by <a href="http://scipy.org/scipy/scikits/wiki/OpenOpt">OpenOpt</a>. After lots of extensive development and nasty testing,  today, I proudly announce that the python interface of ipopt, aka, <a href="http://code.google.com/p/pyipopt/">pyipopt</a>, version alpha, is ready to go.</p>
<p>With the help of this module, in python, you can just use</p>
<blockquote><p>import pyipopt<br />
nlp = pyipopt.create(n, xl, xu, m, gl, gu, nnzj, nnzh, f, gradf, g, gradg, h, apply_new)<br />
solution = nlp.solve(x0)</p></blockquote>
<p>to get your NLP problem which n variables (xl, xu are boundaries for variables), m constraints (gl, gu are boundaries for constraints), and objective function f (gradf is the gradient, h is the Hessian matrix) with constraints g (gradg is the Jacobian value) optimized by IPOPT.</p>
<p>The package is available via google code: <a href="http://code.google.com/p/pyipopt/"><strong>http://code.google.com/p/pyipopt/</strong></a>   An OpenOpt hooker is under development.</p>
<p>The code has BSD license. you can use this module whatever you want. For bug report and other related things, reach me at youxu AT wustl.edu.</p>
<p>To write a  package is not rocket science, but it might save you some time in your research.</p>
<p>[Special thanks to Dmitrey Kroshko from <a href="http://scipy.org/scipy/scikits/wiki/OpenOpt">OpenOpt</a> and <a href="http://www.scipy.org/">Scipy</a> community; Dominique Orban from <a href="http://nlpy.sourceforge.net/">Nlpy</a> community]</p>
<div id="google_plus_one"><g:plusone></g:plusone></div>]]></content:encoded>
			<wfw:commentRss>http://blog.youxu.info/2008/05/10/pyipopt-python-marries-with-ipopt/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>几个趁手语句</title>
		<link>http://blog.youxu.info/2008/03/20/some-handy-scripts/</link>
		<comments>http://blog.youxu.info/2008/03/20/some-handy-scripts/#comments</comments>
		<pubDate>Fri, 21 Mar 2008 03:39:19 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Cool Stuff]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.youxu.info/2008/03/20/some-handy-scripts/</guid>
		<description><![CDATA[处于局域网中的小型开发团队常常需要互相贴代码, 传文件, 共享资源, 我长期使用过程中总结了几行趁手的语句, 贴出来共享. (本文不适合 windows 用户) 1. Gtalk 传递命令行程序输出信息 常常需要... ]]></description>
			<content:encoded><![CDATA[<p>处于局域网中的小型开发团队常常需要互相贴代码, 传文件, 共享资源, 我长期使用过程中总结了几行趁手的语句, 贴出来共享.  (<em>本文不适合 windows 用户</em>)</p>
<p><strong>1. Gtalk 传递命令行程序输出信息</strong></p>
<p>常常需要把程序的输出结果或者调试结果通过 IM 发给同事诊断. 而这些结果通常都在字符界面下，拷贝出来很麻烦，于是，我写了一个小程序<a href="http://blog.youxu.info/gpipe.py"> gpipe.py</a>，可以把 gtalk 当作一个管道接在程序后面, 比如说, 想把程序编译结果给郝培强(tinyfool),</p>
<p><span style="color: #0000ff;">make 2&gt;&amp;1 | gpipe tinyfool</span></p>
<p>他的gtalk 客户端就被我用输出给淹没了.<br />
有兴趣的还可以套接 gtalk, 把信息用 base64 编码, 接受方再解码, 如此一来, gtalk 就和Linux 中的管道一样, 将一个机器上的程序的输出套接到另一个机器上另一个程序的输入. 实践证明, 在跨平台的环境下这种做法比使用中间文件分别执行高效很多. 调试时间也大大减少.</p>
<p><strong>2. 传送文件作为邮件附件. </strong></p>
<p>使用matt 客户端，一行即可完成:<br />
<span style="color: #0000ff;"> echo &#8220;Content&#8221; | mutt -s &#8220;Subject&#8221; -a file email@address.demo<br />
</span><br />
这个方法对及时传输一些小文件非常有效, 特别是传送源代码. 还能起到存档备份的效果, 反正Gmail 那么大不用也浪费.  懒人还可以进一步用一个脚本包装, 比如我机器上就包装出了一个 sendboss.sh, 里面是:<br />
<span style="color: #0000ff;"> echo &#8220;Hi, These are the file(s), thanks. Eric&#8221; | mutt -s &#8220;File&#8221; -a $*  myboss_email@wustl.edu<br />
</span></p>
<p>这样我每次就只要<span style="color: #0000ff;"> &#8220;sendboss.sh files&#8221; </span>就可以了. 我老板常常惊讶于我发送文件的反应速度.</p>
<p><strong>3. 一行语句的HTTP文件服务器.<br />
</strong><br />
<span style="color: #0000ff;"> python -m SimpleHTTPServer</span></p>
<p>即可将当前目录开设为一个8000端口的http 服务器的根目录. 在局域网中，如果需要临时共享当前目录下的一个较大文件，这个方法简便安全，实在是居家旅行必备.</p>
<p>还有, 下载的时候使用 <span style="color: #0000ff;">&#8220;wget -c&#8221;</span> 可以断点续传，很多哥们好像不知道这个小花招.</p>
<p><strong>4. NFS 共享文件夹 </strong></p>
<p>SVN 和 CVS 对于代码和文档控制得很好，可是团队中免不了有些 PDF 文档或者色戒电影需要全团队共享，又不需要送到版本控制系统里面。一个共享的文件夹很有必要. 最简单的方法是使用  NFS, 能够跨平台且性能稳定. 具体服务器设置可以参考<a href="http://nfs.sourceforge.net/nfs-howto/">这里</a>，客户端只要</p>
<p><span style="color: #0000ff;">mount nfs_server:/dir /mnt/share</span></p>
<p>即可顺利使用此文件夹. 此法对于有电驴 bt 爱好者存在的团队来说，实在是必备良方.</p>
<div id="google_plus_one"><g:plusone></g:plusone></div>]]></content:encoded>
			<wfw:commentRss>http://blog.youxu.info/2008/03/20/some-handy-scripts/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>循环迭代器和闭包</title>
		<link>http://blog.youxu.info/2008/03/06/iterator-and-closure/</link>
		<comments>http://blog.youxu.info/2008/03/06/iterator-and-closure/#comments</comments>
		<pubDate>Thu, 06 Mar 2008 23:15:04 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[CompSci]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.youxu.info/2008/03/06/iterator-and-closure/</guid>
		<description><![CDATA[通常, C 程序员使用如下代码对 a 数组的每个元素进行操作: for (i = 0; i &#60; n; i++) func(a[i]); 这行代码有三个独立的逻辑, for 循环控制了对 a 的访问顺序, a[i] 控制了对 a 数组的元素访问方式, func() ... ]]></description>
			<content:encoded><![CDATA[<p>通常, C 程序员使用如下代码对 a 数组的每个元素进行操作:</p>
<blockquote><p>for (i = 0; i &lt; n; i++)  func(a[i]);</p></blockquote>
<p>这行代码有三个独立的逻辑, for 循环控制了对 a 的访问顺序, a[i] 控制了对 a 数组的元素访问方式, func() 函数控制了对 a  元素的操作. 这个三个逻辑是彼此独立的. 然而, 问题逐渐浮出水面. 首先是 for 循环的次序. 对于随机存取的数组 a, 访问顺序应当是没有关系的. for( i=n-1; i&gt;=0; i&#8211;) 也是可以的. 一个简洁的语言应当突出逻辑, 丢掉不必要的代码. 因此, 最好能写成</p>
<blockquote><p> foreach (k in a)  func(k);</p></blockquote>
<p>这个解一石二鸟, 第一是把访问顺序逻辑彻底抛弃, 第二是改变了访问方式, 从此没有烦人的 <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ArrayIndexOutOfBoundsException.html">ArrayIndexOutOfBoundException</a>, 不需要担心访问越界. 在函数式编程语言中, 类似的形式是:</p>
<blockquote><p>map(func, a)</p></blockquote>
<p>我们希望  foreach  能够遍历一个数据结构的每个元素一次. 可是这个终究是一个<a href="http://en.wikipedia.org/wiki/Syntactic_sugar">语法糖</a>, 因为它只能胜任特定的数据结构. 对于用户自己设计的一些数据结构, 比如树, 想同时拥有先序和后序遍历, foreach 就无能为力了. 与此同时, 我们也不想用 for 那样简单粗暴的方式去控制访问顺序 (因为很容易导致内存越界, 而且很多数据结构不支持随机存取).  这时候, 就需要<a href="http://en.wikipedia.org/wiki/Iterator">迭代器</a>的帮助了. 因为不同的数据结构要求不同的访问顺序, 我们希望数据结构本身能够提供一些访问顺序. <em>这种对于数据结构上元素访问顺序的抽象,  被称为迭代器.</em>  一般来说, 迭代器通过 getIterator() 被数据结构构造, 具有一个 hasNext() 的判断和一个 next() 的函数. 对一个数据结构的访问<span style="font-weight: bold">可以四海一家的</span>写成:</p>
<blockquote><p>for (i = a.getIterater(User&#8217;s_Order); i.hasNext(); i.next() )            func(i.current());</p></blockquote>
<p>迭代器把访问逻辑从数据结构上分离出来, 是一个常用的设计方法. Design Pattern 也把它<a href="http://en.wikipedia.org/wiki/Iterator_pattern">作为23个Pattern之一</a>.在 STL 中也到处都是了它的身影. 但对一个完美主义者来说, 这个代码还是太冗长, 既然对数据结构的访问能够四海一家的写成如此, 为何不直接规定一个简洁的语法访问呢? 是的, 我们希望返朴归真, 回到原来的形式:</p>
<blockquote><p>for i in a.SomeIterator(): func(i)</p></blockquote>
<p>好消息是现代语言都支持这样的方法. [注: 在C/C++ 语言中, 还不能支持上面的写法. C#有类似的写法.  在 Ruby 和 Python 中很常见. ] 可是能不能再简化呢, 能不能连 i 这个中间变量都不要呢? 我们简直希望写成:</p>
<blockquote><p>a.SomeIterator(func)</p></blockquote>
<p>是呀, 这样的世界多美好啊. 可是, 别忘了在面向对象的语言中间, 一切都是对象. 在 C 的时代, 我们可以通过函数指针把 func 参数传递进去. 可是这里是对象, 怎么办呢. 很简单, 只要构造一个只有一个方法的对象, 传进去就行了. 这样的构造方法, 居然也是一个设计模式, 叫做<a href="http://en.wikipedia.org/wiki/Function_object">函数对象(Function Object)</a>, 或者叫函数子 (Functor). 被 Java 的<a href="http://en.wikipedia.org/wiki/Inner_class">匿名内部类</a>这个概念折腾到崩溃的读到这里, 应该知道所谓的匿名内部类, 就是为了在面向对象的环境中做函数传递这个事情而想出来的小花招. Java 的写法就是</p>
<blockquote><p>a.SomeIterator( new FunctionObject()<br />
{ public func(a)<br />
{return something;}<br />
});</p></blockquote>
<p>［为了引用这样一个函数, 使用了天书一般的不必要代码, 可想有多少人真的喜欢这个方法］</p>
<p>逃离了Java 的世界, 我们来到 Python 或者 Ruby 或者其他函数式语言的世界, 激动的发现原来函数也是一种对象, 和其他对象一样在 Python 中坐上头等舱. 如此好事怎么能错过呢. 于是, 大摇大摆写上:</p>
<blockquote><p>a.SomeIterator(func)</p></blockquote>
<p>没有类型检查, 也没有复杂代码, 连一个辅助变量都不多谢,  真舒服. 在 Python 中间, 这样的模式比比皆是, 比如 os.path.walk(path, visit, arg) 可以对path目录下所有的文件遍历, 并且调用 visit 函数处理, 还可以夹带一个私货 arg 进去, 非常方便. [注: os.walk() 则反其道行之, 提供一个 generator,  外部用 for 访问]</p>
<p>从外面夹带私货不算特别困难, 毕竟可以通过修改函数的定义方式来实现. 可是假如想从迭代器里面夹带一些私货出来给函数用, 就有点困难了. 比如说, func 函数需要访问迭代器的一个私有的变量. 显然把迭代器作为参数传给函数是不行的. 只能反其道行之, 让迭代器把函数当成自己人, 以迭代器为主, 把函数包含到迭代器的作用域内才能玩转.<em> 这个就是所谓的闭包. 也就是说, 一个函数被包入另一个更大的作用域, 并且可以访问大的作用域里面的变量.</em> C/C++ 是不允许在函数里面定义函数的, 所以只好望着闭包干羡慕. Java 算不错了, 用内部类解决了这个问题.</p>
<p>我们说个具体的例子: 函数 func(x) 需要另一个值 y, 返回 x*y, 另一个值 y 在外部作用域定义了. 写成 Python 代码</p>
<blockquote><p> a= [1, 2, 3]<br />
def func(x):<br />
return x*y</p>
<p>for y in a:<br />
print func(2)</p></blockquote>
<p>会出现 2,4,6</p>
<p>我们可以看到, 函数func 的定义和使用是独立的. 而静态语言是不能随便在什么位置都能定义函数闭包的, 原因不难解释: 编译器会跳出来告诉你 y 这个变量没有定义. 因为动态语言在运行时才能得到 y 的值, 从而使用 func, 所以不存在这个问题. 动态语言的灵活性在此充分展现. 最后, 既然我们知道迭代器后面必然要加一个闭包, 还要括号干啥? 不如直接写成 (实际上, <a href="http://groovy.codehaus.org/">Groovy</a> 语言就是这样的):</p>
<blockquote><p>a.each func</p></blockquote>
<p>从简单的循环, 到迭代器, 到生成器, 到内部类, 到函数作为一级对象, 再到闭包, 过程式编程语言, 对象编程语言和函数编程语言越来越呈现融合的趋势.</p>
<div id="google_plus_one"><g:plusone></g:plusone></div>]]></content:encoded>
			<wfw:commentRss>http://blog.youxu.info/2008/03/06/iterator-and-closure/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>说 Python 的几句坏话</title>
		<link>http://blog.youxu.info/2007/11/29/bad-python/</link>
		<comments>http://blog.youxu.info/2007/11/29/bad-python/#comments</comments>
		<pubDate>Thu, 29 Nov 2007 17:27:28 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Memo]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://blog.youxu.info/2007/11/29/bad-python/</guid>
		<description><![CDATA[我一直很推崇使用 Python, 但是推崇不是迷信, 今天就说说几个 Python 相对于 Java 和其他语言的缺点, 以及初学者要注意什么. 1. 文档不完善, 最少惊奇原则不适用 很多 C++ 和 Java 开发者都知道, MSDN ... ]]></description>
			<content:encoded><![CDATA[<p>我一直很推崇使用 <a href="http://www.python.org/">Python</a>, 但是推崇不是迷信, 今天就说说几个 Python 相对于 Java 和其他语言的缺点, 以及初学者要注意什么.<br />
<strong><br />
1. 文档不完善, 最少惊奇原则不适用</strong></p>
<p>很多 C++ 和 Java 开发者都知道, <a href="msdn.microsoft.com/">MSDN</a> 和<a href="http://java.sun.com/javase/6/docs/api/"> Java Doc</a> 堪称技术文档的典范. Java 更是充分体现 Knuth 提出的 <a href="http://www-cs-faculty.stanford.edu/~knuth/lp.html">Literate Programming</a> 的精华, 用一个专门的叫 javadoc 的工具自动提取程序元信息, 生成交叉引用的 JavaDoc 文档. 任何复杂的类, 框架, 在javadoc 的统一管理下, 可以生成非常漂亮的文档. 如果再配合设计模式中的 facade 模式, 一个复杂的框架很简单就可以上手. 这方面, <a href="http://www.hibernate.org/">Hibernate</a>, <a href="http://lucene.apache.org/">Lucene</a> 都是优秀的典范. 当然, 交叉引用的文档也有明显的缺陷, 就是极其庞大冗长, 因此 JavaDoc 和 JDK 是独立的两个部分. MSDN 更加绝了, 直接出几张光盘, 你爱装不装. 虽然冗长, 好处就是在面向对象的汪洋大海中顺着链接, 永远不会丢失. 而 <a href="http://docs.python.org/lib/">Python 的文档</a>还远远不够细致. 所有的对象方法, 只是简单介绍. 如果一个对象方法返回另外一个不熟悉的对象, 则必须手工定位新对象的位置, 而不能顺着文档继续前进. 为了搞清楚一个包, 完成一个小任务, 可能要多次搜索文档. 对于黑客级别的用户来说, Python 文档言简意赅, 喜闻乐见, 只要记住了每个对象的每个函数, 写程序如行云流水. 对于初学者和用 Python 写稍大项目的人来说, 这就是最恐怖的噩梦. 因为以介绍单个函数功能为组织方式的文档, 对于刚上手的用户来说, 很难顺着对象调用关系，通过文档指引完成任务. 即使著名的框架比如 <a href="http://www.djangoproject.com/">django</a>, 也缺少交叉引用的细致的文档. Python Library Reference 只能说是一个完成了 50% 的README. 在这种情况下, 除非对一个框架很熟悉, 否则这个框架对于初学者来说简直是&#8221;惊奇的噩梦&#8221; &#8212; 一般用户只能看例子然后顿悟到: 哦, 原来是这样用的.</p>
<p>除此以外, 因为语言的动态性, 使得 IDE 能给的帮助特别少. 对于 Java 程序员来说, 很多时候都是靠着 Eclipse 的提示去选择正确的方法调用. 而因为 Python 的动态性, 变量的类型到运行时才能确定, 因此能够给的提示相对变少. Python 既是动态的, 又是强类型的, 所以代码的阅读者必须要一步一步手工追踪中间对象的类型, 并且查阅对象方法文档, 才能搞清楚到底一段代码做得什么. 而这一切, 偏偏是没有 IDE 帮助的. 对于开发者来说, 如果不熟悉对象的可用方法, 用 Python 开发也会事倍功半, 因为要常常停下来去 Google.</p>
<p>当然, 文档不够完美, IDE 不支持的现状, 根本是因为 Python 的动态性: 谁让 Python 返回值不规定类型呢? 我的建议是, A. 对于现成已知的一些对象方法上, Python 社区应该注意文档的维护. B. 对于不熟悉对象的可用方法这个问题, 要买一本<a href="http://www.oreilly.com/catalog/pythonpr3/"> Pocket Reference</a>. 或者下载一些 cheet sheet. <strong>在刚接触 Python 或者 刚接触 Python 框架的时候, 一本薄薄的可供快速查阅所有对象的所有方法的小书, 无比重要.</strong> 这也间接的说明, 和 shell 脚本, 正则表达式语法等一样, 脚本语言必须要很熟悉才能发挥魔力.</p>
<p>(&#8211; 附实例，对Java 不熟悉的可直接跳过: 我曾经做过一个游戏, 这个游戏类似于推箱子, 其中的一个核心是要把多幅带alpha 通道的图像拼成一个图像, 然后显示在窗口中. 打开 API Doc, 简单的搜索一下, 发现有 java.awt.Image 类. 不过这个是抽象类, 没关系, 文档下面就明明白白写着两个可以直接用的类, 一个是 BufferedImage, 另一个是 VolatileImage. 看上去 BufferedImage 更像, 于是点进去, 正是想要的. 看看构造函数, 一个空白的图像就构造好了. 顺着方法向下看, 看到 createGraphics() 方法, 返回 Graphics2D 方法, 说明中写着这个可用做在 Image 上绘图, 正是想要的, 点返回值, 是 Graphics2D, 有方法叫 drawImage. 任务完成, 轻松自然.</p>
<p>回到 Python. 我遇到过一个需求, 是用 Python 提取所有一个 Zip 文件的注释. Google Zip+Python 定位到 zipfile 模块. 找到 ZipFile 对象. 读文档没发现可以往外读注释, 只能碰运气, 开一个解释器尝试. 看上去 getinfo 可以. 因为没有交叉引用, 只能搜索ZipInfo 这个对象. 终于看到一个方法是 comment. 不知道类型, 仍然需要自己在解释器下先 type 测试一下, 才能在程序中写下一行完整的语句.&#8211;)</p>
<p><strong><br />
2.  文档上有, 但是你不能用</strong></p>
<p>我用 Ubuntu/MacOSX系统, Python 是自带的. 以为万事大吉, 实际上, 因为 <strong>Python 所有的库都是运行时装载的, 所以有些库在有些系统上是缺失的, 而文档则是所有标准安装的超集.</strong> 因此即使文档上有, 你也没法用.</p>
<p>这个问题对于 Java 程序员和 .Net 程序员来说是不能接受的. 对于任何一个良好设计的 SDK, 文档和实际可用的应该具有同等的覆盖面. 在 Java 中, 有一个包就是有, 没有就是没有, 绝对不会出现标准文档中提到了, 实际中却不可用的情况. 对于可选包, 用户也能理解需要下载模块. 而对于 Python, 开发人员很难理解为什么标准文档中提到了, 实际中却缺这个组件缺那个组件. <strong>一个潜在的伤害就是, Python 的跨平台能力没那么强.</strong> 试想, 开发的机器上有一个模块, 而用户没有. 而标准文档偏偏又认为这个是一个标准组件, 那么, 在装载的时候，找不到这个组件了, 让用户根本就无从下手. 我的建议是 A. Python 应当有更好的 import 报错机制, 对于不是每台机器都安装的模块, 应当给出平台中立的更加友好的帮助信息, 而不是简单的 ImportError. B. 应当在 Python 语言中支持更加强大的内省机制, 对于系统当前可用的包, 应当有一个全局的缓存. 这样, 用户才能知道哪些可用哪些不可用, 不可用的时候怎么办. C. 对于用户来说, 只能求助于Google 或新闻组, 或者从 Python 源代码中找线索. 一个较好的办法是在 Python 源代码上 执行 make test, Python 会汇报哪些模块已经编译, 哪些模块被跳过了.</p>
<p>(&#8211;实例: 前几天想写个程序抓Google Reader. 认证的时候要用到 SSL. 因此找到 Python 文档, 照着例子 import urllib2, 然后直接连 Https 服务器. 出错了, 原因是没有 ssl 支持, 不能访问 https. 所有的 Python 在线文档都说, 这个是标准模块. 对呀, Python Library Reference 里面都有的模块, 怎么能有问题呢? Google 搜索也帮不了什么忙, 因为 Python 是跨平台的, 不同的平台有不同的解决方法. 所有的在线帮助只能提示到 _ssl.o 这一层. 于是, 只能翻看 Python 源代码, 在 Modules/_ssl.c 中看了一圈, 发现需要 openssl/ssl.h 等文件, 这才意识到, 需要安装 openssl 和 libssl-dev. <em>在 Ubuntu 上, 同样的问题还存在于 sqlite3 模块, tk 模块 和 bz2 模块. 分别需要安装 libsqlite3-dev, tk-dev 和 libbz2-dev, 再重新编译 Python 系统. 使用 make; python setup.py install 来安装 </em>&#8211;)</p>
<p><strong>3. Python 是胶水语言, 用是简单的, 模块开发是痛苦的</strong></p>
<p>Python 用到一定程度以后, 一个自然的需求就是把其他语言, 特别是C语言写的库包装成 Python 库. 这个问题说复杂也不复杂, 在 Python/C Reference Manual 中也提到了所有必要的信息. 只是层次太细. <a href="http://www.boost.org/libs/python/doc/">Boost.Python</a> 有更加好的实现, 不过需要对 C++ 模板很熟悉才行. 当然, Python 的模块开发的痛苦比起 <a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/index.html">JNI</a> 复杂的 JNIEnv 对象, <a href="http://www.lua.org/">Lua</a> 的 基于栈的 Push Pop 已经是大大轻松了. 相比较于 <a href="http://www.ruby-lang.org/en/">Ruby</a> 的自动生成 makefile, 也算各有千秋. 只是模块开发设计到的技术细节太多, 要对 Python/C API 了然于胸才行. 因此我的建议是: 不要从轮子造起. 如果有这样的模块, 就用.<strong> 如果没有, 而又非要用特定功能的模块不可, 那就暂时先不要考虑用 Python. 相比较于其他更加成熟的语言, 比如 Java, Python 的可用模块还是显得少了一点. </strong>因为 <a href="http://www.jython.org/Project/index.html">Jython</a> 的出现, 这个情况已经大大缓解. 不过工业界历来喜欢用最稳定的东西, 所以可以想象, 多少 Web2.0 公司是为了用 Lucene 才用 Java 服务器的, 而每天又有多少新的公司投入 Java 的怀抱 :)</p>
<div id="google_plus_one"><g:plusone></g:plusone></div>]]></content:encoded>
			<wfw:commentRss>http://blog.youxu.info/2007/11/29/bad-python/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>语言模型与语言识别程序 -1</title>
		<link>http://blog.youxu.info/2007/11/13/language-model-and-detector/</link>
		<comments>http://blog.youxu.info/2007/11/13/language-model-and-detector/#comments</comments>
		<pubDate>Tue, 13 Nov 2007 06:31:24 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[CompSci]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.youxu.info/2007/11/13/language-model-and-detector/</guid>
		<description><![CDATA[[先说一下, 上次的语言识别程序的思路来自 Python Cookbook, 我只是略作修改, 并没有什么太大的贡献, 这个系列可能包含三到四篇文章. 底下我可能会用朴素贝页斯分类器再写一个然后比较两者效... ]]></description>
			<content:encoded><![CDATA[<p>[先说一下, 上次的语言识别程序的思路来自 <a href="http://aspn.activestate.com/ASPN/Python/Cookbook/">Python Cookbook</a>, 我只是略作修改, 并没有什么太大的贡献, 这个系列可能包含三到四篇文章. 底下我可能会用朴素贝页斯分类器再写一个然后比较两者效果]</p>
<p>以前我在翻译<a href="http://blog.youxu.info/spell-correct.html">怎样写一个拼写检查器</a>中, 就提到了(概率)语言模型这个东西. 什么是语言模型呢, 简单的说, 就是这个语言当中, 每个词出现的概率分布是有一定规律的, 与其他因素无关的. 如果我们要写一个汉语到英文的翻译器, 那么, 理论上说, 我们翻译器输出来的结果当中每个单词出现的概率, 应该和英文当中每个词出现的概率一样. 试想一下, the 这个单词在英文中常常出现, 而如果我们的翻译器对于任意汉语的翻译结果中, 故意调低或者错误设置 the 出现的概率, 造成翻译出来的结果几乎不出现 the, 或者出现的概率出奇的奇怪, 那么, 这段翻译出来的话, 它怎么看也不会像英语. 同样的道理, 一个拼写检查器可以把任意拼错的单词纠正过来, 在纠正过程中必须照顾到语言模型. 如果 teh 可以被改正为 the 和 tek, 那么我们应该优先考虑 the 才对, 因为 the 被使用的概率比 tek 大. (统计语言模型整体是很大的一块, 大家可以去读 <a href="http://www.googlechinablog.com/2006/04/blog-post.html">Google 黑板报数学之美系列</a>得到一个大致的感觉. 我这里只用到语言模型, 用不到条件概率)</p>
<p>基于这个假设, 我们自然的得到一个主意: 好呀, 假如两个文本的语言模型类似, 我们就认为他们是同种语言写成的. 对的, 怎么衡量这个类似呢, 我们可以用数学的方法: 统计任何两个语言模型之间的&#8221;距离&#8221;, 然后选取最小的. 这个地方距离随便怎么定义, 可以用向量夹角, 可以用欧式距离. 但是, 现实的问题不是这么简单. 首先, 如果每个词都对应一个词频的话, 得到的向量是高维的. 除非有一个包含各种语言单词的全集, 否则很难说这个向量一共要有多少个维度. 而且高维的随机向量还往往以很大的概率正交. 为了控制维度灾难, 一个简单的方法是使用每一个字节作为一个词统计. 这个模型虽然看上去很没道理, 而且还很&#8221;面向机器&#8221;, 但是考虑到计算机处理语言的时候本来也就是根据字节来处理, 这样做一下也未尝不可.</p>
<p>我并没有亲自实践比较字节频率然后计算向量距离的方法, 不过我可以想像, 这样的方法在UTF-8字符集上是有很好表现的. 有人可能会担心, 加入某个汉字编码成了两个字节, 这两个字节正好分别等于西文字母的编码的话, 汉字就可以在计算机中等价的写成一串字母了, 这样, 就很难保证一段汉字是不是和一段希腊文正好有同样的字节分布了, 因为我们可以作弊一下, 搞出一段汉字, 正好和希腊文对应分布一样. 但是, 巧妙之处在于<a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8 字符集</a>本身通过若干前缀区分了不同的变长编码, 不同的编码区段没有任何交集. 反过来说就是, 从UTF-8 编码的字节序列中任意取一个字节出来, 一定能够区分这个字节是某个变长编码的一部分. 任何一个多字节符号编出来的编码的一部分, 绝对不可能正好是其他单字节符号的编码. 这样, 单字节多字节变成字节编码后各自为政, 映射到的字节码的概率分布不会出现“作弊”现象. 用严格的数学语言来说就是, 一个字符对应的字节在叠加到向量中的时候, 绝对不会叠加到属于另一个字符的所有字节上, 也就是说, 他们总有独立分布的部分存在. 这个是字节模型能正确反映语言模型的一个必要要求.</p>
<p>[To be continued...]</p>
<div id="google_plus_one"><g:plusone></g:plusone></div>]]></content:encoded>
			<wfw:commentRss>http://blog.youxu.info/2007/11/13/language-model-and-detector/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Practical Guide to the AIMA Python Code 2</title>
		<link>http://blog.youxu.info/2007/10/05/a-practical-guide-to-the-aima-python-code-2/</link>
		<comments>http://blog.youxu.info/2007/10/05/a-practical-guide-to-the-aima-python-code-2/#comments</comments>
		<pubDate>Fri, 05 Oct 2007 05:47:51 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[CompSci]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.youxu.info/2007/10/05/a-practical-guide-to-the-aima-python-code-2/</guid>
		<description><![CDATA[Continued with the last post Some readers reported that if using graph_search to solve the NQueensProblem provided in search.py, python will complain that: TypeError: list objects are unhashable Yes, you are doing perfectly right and the code itself is i... ]]></description>
			<content:encoded><![CDATA[<p>Continued with the <a href="http://blog.youxu.info/2007/10/04/a-practical-guide-to-the-aima-python-code-1/">last post</a></p>
<p>Some readers reported that if using <code>graph_search</code> to solve the <code>NQueensProblem</code> provided in search.py, python will complain that:<br />
<code><br />
TypeError: list objects are unhashable</code></p>
<p>Yes, <strong>you are doing perfectly right</strong> and <strong>the code itself is imperfect</strong>. As this point, you might want to make the List objective hashable. Inspired by the idea of Set and FrozenSet in Python, you would expect a frozen(x) function to make any mutable object immutable (and therefore hashable) [Or you can try to use tuple from beginning, but in the <code>NQueensProblem</code> code, it uses <code>.index</code> method, which is only suitable for List]. Unfortunately, this proposal (PEP-351) was <a href="http://aspn.activestate.com/ASPN/docs/ActivePython/2.5/peps/pep-0351.html">rejected by </a><em><a href="http://aspn.activestate.com/ASPN/docs/ActivePython/2.5/peps/pep-0351.html">Guido</a>.  </em>Hence, we don&#8217;t have a unified way to convert any &#8220;state&#8221; to an immutable object and insert it in to &#8220;closed table&#8221;. One possible way to do this is to write your own State class and implement the<code> __hashcode__</code> function. The other handy but awkward way is to convert the list to a tuple when insterting to the &#8220;closed table, i.e. edit <strong>Line 144 of search.py</strong> as:</p>
<p><code>if tuple(node.state) not in closed:<br />
closed[tuple(node.state)] = True</code></p>
<p>Here is a toy forzen function.</p>
<pre><tt></tt><tt><em><font color="#9a1900">"""Toy function frozen which can convert mutable objects to immutable</font></em>
<em><font color="#9a1900">	Author: Eric You XU.</font></em>
<em><font color="#9a1900">	GPLv2</font></em>
<em><font color="#9a1900">"""</font></em>

<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">frozen</font></strong><font color="#990000">(</font>x<font color="#990000">)</font><font color="#990000">:</font>
<em><font color="#9a1900">	"""Return the immutable version of an object.</font></em>
<em><font color="#9a1900">	"""</font></em>
	<strong><font color="#0000ff">if</font></strong> <strong><font color="#000000">type</font></strong><font color="#990000">(</font>x<font color="#990000">)</font> <font color="#990000">=</font><font color="#990000">=</font> <strong><font color="#000000">type</font></strong><font color="#990000">(</font><font color="#990000">[</font><font color="#990000">]</font><font color="#990000">)</font><font color="#990000">:</font>
		<strong><font color="#0000ff">return</font></strong> <strong><font color="#000000">tuple</font></strong><font color="#990000">(</font>x<font color="#990000">)</font>
	<strong><font color="#0000ff">elif</font></strong> <strong><font color="#000000">type</font></strong><font color="#990000">(</font>x<font color="#990000">)</font> <font color="#990000">=</font><font color="#990000">=</font> <strong><font color="#000000">type</font></strong><font color="#990000">(</font><font color="#990000">[</font><font color="#990000">]</font><font color="#990000">)</font><font color="#990000">:</font>
		<strong><font color="#0000ff">raise</font></strong> <font color="#ff0000">"I can't froze dictionary object as they are very hot."</font>
	<em><font color="#9a1900"># fill your type here</font></em>
	<strong><font color="#0000ff">else</font></strong><font color="#990000">:</font>
		<strong><font color="#0000ff">return</font></strong> x</tt></pre>
<p>You can put it in to search.py and edit the Line 144 as:</p>
<p><code>if frozen(node.state) not in closed:<br />
colsed[</code><code>frozen</code><code>(node.state)] = True</code></p>
<p>Now the code looks much better.</p>
<div id="google_plus_one"><g:plusone></g:plusone></div>]]></content:encoded>
			<wfw:commentRss>http://blog.youxu.info/2007/10/05/a-practical-guide-to-the-aima-python-code-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A practical guide to the AIMA Python code -1</title>
		<link>http://blog.youxu.info/2007/10/04/a-practical-guide-to-the-aima-python-code-1/</link>
		<comments>http://blog.youxu.info/2007/10/04/a-practical-guide-to-the-aima-python-code-1/#comments</comments>
		<pubDate>Thu, 04 Oct 2007 05:28:05 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[CompSci]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.youxu.info/2007/10/04/a-practical-guide-to-the-aima-python-code-1/</guid>
		<description><![CDATA[Part -1 Search Introduction AIMA (Artificial Intelligence: A Modern Approach) might be the most successful textbook about AI. I take this course with Prof. Yixin Chen this semester. I am going to go through all the source code (Python) provided on the we... ]]></description>
			<content:encoded><![CDATA[<p>Part -1 Search</p>
<p><strong>Introduction</strong></p>
<p><a href="http://blog.youxu.info/wp-content/uploads/2007/10/images.jpg" title="images.jpg"><img src="http://blog.youxu.info/wp-content/uploads/2007/10/images.jpg" title="images.jpg" alt="images.jpg" align="right" border="2" /></a>   AIMA (Artificial Intelligence: A Modern Approach) might be the most successful textbook about AI. I take this course with Prof. Yixin Chen this semester. I am going to go through all the source code (Python) provided on the website and use them to finish my homework. Therefore, both for my personal referral purpose and for someone who might be interested in using that code, I write a very simple &#8220;practical guide to AIMA python source code&#8221; series here. Enjoy the magic of AI and Python!<br />
<strong> Step 1, build the environment. </strong></p>
<p>In this section, you will need three python files:</p>
<p>http://aima-python.googlecode.com/svn/trunk/agents.py</p>
<p>http://aima-python.googlecode.com/svn/trunk/search.py</p>
<p>http://aima-python.googlecode.com/svn/trunk/utils.py</p>
<p>Type:<br />
<code>python agents.py</code><br />
and<br />
<code>python search.py</code></p>
<p>to make sure that you have all the packages like Image and Tk  with your python. If you don&#8217;t have them, just download them. The general guideline is to use apt-get if possible. If you are not using Debian family OS, download the Python package and then use</p>
<p><code>python setup.py<br />
</code><br />
at the python package folder.</p>
<p><strong>Step 2, study the code &#8212; tree search<br />
</strong><br />
In order to use the code, we have to get familiar with the interface. Let&#8217;s get start from search.py and start from <code>depth_first_tree_search</code> (Line 130). The line reads:</p>
<p><code>def depth_first_tree_search(problem):<br />
return tree_search(problem, Stack())</code></p>
<p>We all know that depth-first search uses Stack. Now let&#8217;s omit the technical detail about the implementation of Stack in util.py and check what the &#8220;problem&#8221; is.</p>
<p>Let&#8217;s move to Line 16 of search.py. Here is the definition of Problem class. Here<code> __init__ </code> just assigns the initial state. All functions like successor and goal_test are abstract. So, let&#8217;s take a look a concrete example. Let&#8217;s jump to Line 458, <code>NQueenProblem</code>. It&#8217;s a subclass of Problem. It defines the initial state, <code>successor</code> function, and <code>goal_test</code> function. Node that the function <code>conflicted</code> and <code>conflict</code> are for internal use only, there are not the essential part of a problem.</p>
<p>Here, by this case study, we at least know that we have to define a problem with</p>
<p>1. <code>self.initial</code> field which is the starting point for a problem.<br />
2. A <code>successor</code> function which generate the successor state for a given state. We will study it carefully later.<br />
3. A <code>goal_test</code> function which returns either False or True.</p>
<p>The initial is really trivial, we can just assign a initial state to it. Note that Python is a dynamic type language, so we don&#8217;t actually care about what type of state is. We will exam the type of state later, but now let&#8217;s assume that we know the type of state.</p>
<p>The <code>successor</code> function is really tricky. A straight-forward way to design a successor function will return all possible states in a list. But if you do that, you will get an &#8220;Too many values to unpack&#8221; error. The design here is actually very neat: instead of put a state in to the list, you can put a (action, state) tuple in to a list. [Line 88 of search.py, in</p>
<p><code>function expand(problem)<br />
...<br />
for (act, next) in problem.successor(self.state)</code></p>
<p>read this line and you will figure out the date structure to store the successors. The reason is also simple: we can trace the path easily if you record the action down at every expanding step.</p>
<p>Since we moved our eyes to the Node class, let's exam it carefully.</p>
<p>The constructor of Node is fairly simple. The <code>path</code> function will backtrack all the path to the root. We can modify the code of <code>__repr__</code> here to print the action out if needed. If any search finally return a result in the form of <code>Node</code>, we can actually get everything we need from this Node, e.g., the path to the node, the action series to the node.</p>
<p>Based on the knowledge above, you can write your own problem model based on tree search. Now let's move on to graph search.</p>
<p>Step 3. Graph search.</p>
<p>The only difference between tree search and graph search is that in graph search, we have a fringe that stores the closed notes. As you might know, the fringe is implemented in hash table. In Python, there is a tiny technical point: List is not hash-able as it's mutable, Tuple and String are hash-able. Therefore, if you implement your state as a list, make sure to convert it to a tuple or string or a constant. Otherwise graph search will not be happy with this and complain about it.</p>
<p>If you want to use A* search, another point arises: heuristic function. Note that Line 211 reads:</p>
<p><code>def f(n):<br />
return max(getattr(n, 'f', -infinity), n.path_cost + h(n))<br />
</code><br />
here n is a Node instead of a State. Hence, if you want to get the state information and implement h, you have to use n.state to get the state information.</p>
<p><strong>Step 4. build your application</strong></p>
<p>Perhaps the best part to study the code is to write your own code to test it. Here are my implementations on eightpuzzle and three-missionaries three cannibals problem. The code is ugly and only for study purpose only.<em> Please don't directly copy it to your homework.<br />
</em><br />
<a href="http://blog.youxu.info/eightpuzzle.py">Eightpuzzle.py</a></p>
<pre><tt><em><font color="#9a1900">#!/usr/bin/python</font></em>

<strong><font color="#0000ff">from</font></strong> utils <strong><font color="#0000ff">import</font></strong> <font color="#990000">*</font><font color="#990000">;</font>
<strong><font color="#0000ff">from</font></strong> search <strong><font color="#0000ff">import</font></strong> <font color="#990000">*</font><font color="#990000">;</font>

<strong><font color="#0000ff">class</font></strong> <strong><font color="#000000">EightPuzzle</font></strong><font color="#990000">(</font>Problem<font color="#990000">)</font><font color="#990000">:</font>
<em><font color="#9a1900">	"""The problem of solving a eight puzzle problem """</font></em>
	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">__init__</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> state<font color="#990000">)</font><font color="#990000">:</font>
		self<font color="#990000">.</font>initial <font color="#990000">=</font> <strong><font color="#000000">tuple</font></strong><font color="#990000">(</font>state<font color="#990000">)</font>

	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">successor</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> state<font color="#990000">)</font><font color="#990000">:</font>
<em><font color="#9a1900">		"""In the 8 puzzle problem, move the blank to other position."""</font></em>
		result <font color="#990000">=</font> <font color="#990000">[</font><font color="#990000">]</font>
		position <font color="#990000">=</font> <strong><font color="#000000">list</font></strong><font color="#990000">(</font>state<font color="#990000">)</font><font color="#990000">.</font><strong><font color="#000000">index</font></strong><font color="#990000">(</font><font color="#993399">0</font><font color="#990000">)</font>
		<strong><font color="#0000ff">for</font></strong> action<font color="#990000">,</font> newposition <strong><font color="#0000ff">in</font></strong> self<font color="#990000">.</font><strong><font color="#000000">possible_position</font></strong><font color="#990000">(</font>position<font color="#990000">)</font><font color="#990000">.</font><strong><font color="#000000">iteritems</font></strong><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">:</font>
			new <font color="#990000">=</font> <strong><font color="#000000">list</font></strong><font color="#990000">(</font>state<font color="#990000">[</font><font color="#990000">:</font><font color="#990000">]</font><font color="#990000">)</font>
			new<font color="#990000">[</font>newposition<font color="#990000">]</font><font color="#990000">,</font> new<font color="#990000">[</font>position<font color="#990000">]</font> <font color="#990000">=</font> new<font color="#990000">[</font>position<font color="#990000">]</font><font color="#990000">,</font> new<font color="#990000">[</font>newposition<font color="#990000">]</font>
			result<font color="#990000">.</font><strong><font color="#000000">append</font></strong><font color="#990000">(</font><font color="#990000">(</font>action<font color="#990000">,</font> <strong><font color="#000000">tuple</font></strong><font color="#990000">(</font>new<font color="#990000">)</font><font color="#990000">)</font><font color="#990000">)</font>
		<strong><font color="#0000ff">return</font></strong> result

	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">possible_position</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> position<font color="#990000">)</font><font color="#990000">:</font>
<em><font color="#9a1900">		&#8220;&#8221;"return the possible position&#8221;"&#8221;</font></em>
		result <font color="#990000">=</font> <font color="#990000">{</font><font color="#990000">}</font><font color="#990000">;</font>
		col <font color="#990000">=</font> position <font color="#990000">%</font> <font color="#993399">3</font><font color="#990000">;</font>
		row <font color="#990000">=</font> position <font color="#990000">/</font><font color="#990000">/</font> <font color="#993399">3</font><font color="#990000">;</font>
		<strong><font color="#0000ff">if</font></strong> row <font color="#990000">!</font><font color="#990000">=</font> <font color="#993399">2</font><font color="#990000">:</font>
			result<font color="#990000">[</font><font color="#ff0000">'D'</font><font color="#990000">]</font> <font color="#990000">=</font> position <font color="#990000">+</font><font color="#993399">3</font>
		<strong><font color="#0000ff">if</font></strong> col <font color="#990000">!</font><font color="#990000">=</font> <font color="#993399">0</font><font color="#990000">:</font>
			result<font color="#990000">[</font><font color="#ff0000">'L'</font><font color="#990000">]</font> <font color="#990000">=</font> position <font color="#990000">-</font><font color="#993399">1</font>
		<strong><font color="#0000ff">if</font></strong> row <font color="#990000">!</font><font color="#990000">=</font> <font color="#993399">0</font><font color="#990000">:</font>
			result<font color="#990000">[</font><font color="#ff0000">'U'</font><font color="#990000">]</font> <font color="#990000">=</font> position <font color="#990000">-</font><font color="#993399">3</font>
		<strong><font color="#0000ff">if</font></strong> col <font color="#990000">!</font><font color="#990000">=</font> <font color="#993399">2</font><font color="#990000">:</font>
			result<font color="#990000">[</font><font color="#ff0000">'R'</font><font color="#990000">]</font> <font color="#990000">=</font> position <font color="#990000">+</font><font color="#993399">1</font>

		<strong><font color="#0000ff">return</font></strong> result
<em><font color="#9a1900">	</font></em>

	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">goal_test</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> state<font color="#990000">)</font><font color="#990000">:</font>
		<strong><font color="#0000ff">if</font></strong> state<font color="#990000">[</font><font color="#993399">0</font><font color="#990000">]</font> <font color="#990000">!</font><font color="#990000">=</font> <font color="#993399">0</font><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> False
		<strong><font color="#0000ff">elif</font></strong> state<font color="#990000">[</font><font color="#993399">1</font><font color="#990000">]</font> <font color="#990000">!</font><font color="#990000">=</font><font color="#993399">1</font><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> False
		<strong><font color="#0000ff">elif</font></strong> state<font color="#990000">[</font><font color="#993399">2</font><font color="#990000">]</font> <font color="#990000">!</font><font color="#990000">=</font><font color="#993399">2</font><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> False
		<strong><font color="#0000ff">elif</font></strong> state<font color="#990000">[</font><font color="#993399">3</font><font color="#990000">]</font> <font color="#990000">!</font><font color="#990000">=</font><font color="#993399">3</font><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> False
		<strong><font color="#0000ff">elif</font></strong> state<font color="#990000">[</font><font color="#993399">4</font><font color="#990000">]</font> <font color="#990000">!</font><font color="#990000">=</font><font color="#993399">4</font><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> False
		<strong><font color="#0000ff">elif</font></strong> state<font color="#990000">[</font><font color="#993399">5</font><font color="#990000">]</font> <font color="#990000">!</font><font color="#990000">=</font><font color="#993399">5</font><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> False
		<strong><font color="#0000ff">elif</font></strong> state<font color="#990000">[</font><font color="#993399">6</font><font color="#990000">]</font> <font color="#990000">!</font><font color="#990000">=</font><font color="#993399">6</font><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> False
		<strong><font color="#0000ff">elif</font></strong> state<font color="#990000">[</font><font color="#993399">7</font><font color="#990000">]</font> <font color="#990000">!</font><font color="#990000">=</font><font color="#993399">7</font><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> False
		<strong><font color="#0000ff">elif</font></strong> state<font color="#990000">[</font><font color="#993399">8</font><font color="#990000">]</font> <font color="#990000">!</font><font color="#990000">=</font><font color="#993399">8</font><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> False
		<strong><font color="#0000ff">else</font></strong><font color="#990000">:</font>
			<strong><font color="#0000ff">return</font></strong> True 	

	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">h</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> node<font color="#990000">)</font><font color="#990000">:</font>
<em><font color="#9a1900">		&#8220;&#8221;"Heuristic function&#8221;"&#8221;</font></em>
		temp<font color="#990000">=</font><strong><font color="#000000">list</font></strong><font color="#990000">(</font>node<font color="#990000">.</font>state<font color="#990000">)</font>
		sum<font color="#990000">=</font><font color="#993399">0</font>
		<strong><font color="#0000ff">for</font></strong> x <strong><font color="#0000ff">in</font></strong> <strong><font color="#000000">range</font></strong><font color="#990000">(</font><font color="#993399">8</font><font color="#990000">)</font><font color="#990000">:</font>	<em><font color="#9a1900"># mahatten distance</font></em>
			sum <font color="#990000">=</font> sum <font color="#990000">+</font> <strong><font color="#000000">abs</font></strong><font color="#990000">(</font>temp<font color="#990000">.</font><strong><font color="#000000">index</font></strong><font color="#990000">(</font>x<font color="#990000">)</font><font color="#990000">-</font>x<font color="#990000">)</font>
		<strong><font color="#0000ff">return</font></strong> sum

	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">h2</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> node<font color="#990000">)</font><font color="#990000">:</font>
<em><font color="#9a1900">		&#8220;&#8221;"bad h&#8221;"&#8221;</font></em>
		sum <font color="#990000">=</font> <font color="#993399">0</font>
		pos <font color="#990000">=</font> <font color="#993399">0</font>
		<strong><font color="#0000ff">for</font></strong> x <strong><font color="#0000ff">in</font></strong> node<font color="#990000">.</font>state<font color="#990000">:</font>
			sum <font color="#990000">=</font> sum <font color="#990000">+</font> <strong><font color="#000000">abs</font></strong><font color="#990000">(</font>x <font color="#990000">-</font> pos<font color="#990000">)</font>
			pos <font color="#990000">=</font> pos <font color="#990000">+</font> <font color="#993399">1</font>
		<strong><font color="#0000ff">return</font></strong> sum</tt></pre>
<pre><tt><strong><font color="#0000ff">if</font></strong> <font color="#990000">(</font>__name__<font color="#990000">=</font><font color="#990000">=</font><font color="#ff0000">"__main__"</font><font color="#990000">)</font><font color="#990000">:</font>

<em><font color="#9a1900">#	state = [1, 2, 3, 4, 5, 6, 7, 8, 0]</font></em>
	state <font color="#990000">=</font> <font color="#990000">[</font><font color="#993399">7</font><font color="#990000">,</font> <font color="#993399">2</font><font color="#990000">,</font> <font color="#993399">4</font><font color="#990000">,</font> <font color="#993399">5</font><font color="#990000">,</font> <font color="#993399">0</font><font color="#990000">,</font> <font color="#993399">6</font><font color="#990000">,</font> <font color="#993399">8</font><font color="#990000">,</font> <font color="#993399">3</font><font color="#990000">,</font> <font color="#993399">1</font><font color="#990000">]</font>
<em><font color="#9a1900">#	state = (2, 6, 4, 7, 0, 3, 5, 8, 1)</font></em>
	instance <font color="#990000">=</font> <strong><font color="#000000">EightPuzzle</font></strong><font color="#990000">(</font>state<font color="#990000">)</font>
<em><font color="#9a1900">#	breadth_first_tree_search(instance)</font></em>
<em><font color="#9a1900">#	depth_first_tree_search(instance)</font></em>
<em><font color="#9a1900">#	breadth_first_graph_search(instance)</font></em>
<em><font color="#9a1900">#	print depth_first_graph_search(instance).path()</font></em>
	<strong><font color="#0000ff">print</font></strong> <strong><font color="#000000">astar_search</font></strong><font color="#990000">(</font>instance<font color="#990000">,</font> instance<font color="#990000">.</font>h<font color="#990000">)</font><font color="#990000">.</font><strong><font color="#000000">path</font></strong><font color="#990000">(</font><font color="#990000">)</font> </tt></pre>
<p><a href="http://blog.youxu.info/boat.py">Boat.py</a></p>
<pre><tt></tt><tt><em><font color="#9a1900">#!/usr/bin/python</font></em>

<strong><font color="#0000ff">from</font></strong> utils <strong><font color="#0000ff">import</font></strong> <font color="#990000">*</font><font color="#990000">;</font>
<strong><font color="#0000ff">from</font></strong> search <strong><font color="#0000ff">import</font></strong> <font color="#990000">*</font><font color="#990000">;</font>

<em><font color="#9a1900">"""state is a tuple with (#m1, #m2, #s1, #s2, where_is_the_boat)"""</font></em>

<strong><font color="#0000ff">class</font></strong> <strong><font color="#000000">Boat</font></strong><font color="#990000">(</font>Problem<font color="#990000">)</font><font color="#990000">:</font>
	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">__init__</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> state<font color="#990000">)</font><font color="#990000">:</font>
		self<font color="#990000">.</font>initial <font color="#990000">=</font> <strong><font color="#000000">tuple</font></strong><font color="#990000">(</font>state<font color="#990000">)</font>
		self<font color="#990000">.</font>N <font color="#990000">=</font> state<font color="#990000">[</font><font color="#993399">0</font><font color="#990000">]</font>
		self<font color="#990000">.</font>nodenum <font color="#990000">=</font> <font color="#993399">1</font>

	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">successor</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> state<font color="#990000">)</font><font color="#990000">:</font>
		result <font color="#990000">=</font> <font color="#990000">[</font><font color="#990000">]</font>
		symbol <font color="#990000">=</font> state<font color="#990000">[</font><font color="#993399">4</font><font color="#990000">]</font><font color="#990000">*</font><font color="#993399">2</font> <font color="#990000">-</font><font color="#993399">1</font><font color="#990000">;</font> <em><font color="#9a1900"># 0 =&gt; -1</font></em>
		action <font color="#990000">=</font> <font color="#993399">0</font>
		<strong><font color="#0000ff">for</font></strong> x <strong><font color="#0000ff">in</font></strong> <font color="#990000">(</font><font color="#993399">0</font><font color="#990000">,</font> <font color="#993399">1</font><font color="#990000">,</font> <font color="#993399">2</font><font color="#990000">)</font><font color="#990000">:</font>
			<strong><font color="#0000ff">for</font></strong> y <strong><font color="#0000ff">in</font></strong> <font color="#990000">(</font><font color="#993399">0</font><font color="#990000">,</font> <font color="#993399">1</font><font color="#990000">,</font> <font color="#993399">2</font><font color="#990000">)</font><font color="#990000">:</font>
				<strong><font color="#0000ff">if</font></strong> x <font color="#990000">+</font> y <font color="#990000">&gt;</font><font color="#990000">=</font> <font color="#993399">1</font> <strong><font color="#0000ff">and</font></strong> x <font color="#990000">+</font> y <font color="#990000">&lt;</font><font color="#990000">=</font> <font color="#993399">2</font><font color="#990000">:</font>
					new <font color="#990000">=</font> <font color="#990000">(</font>state<font color="#990000">[</font><font color="#993399">0</font><font color="#990000">]</font> <font color="#990000">+</font> symbol<font color="#990000">*</font>x<font color="#990000">,</font> state<font color="#990000">[</font><font color="#993399">1</font><font color="#990000">]</font><font color="#990000">-</font>symbol<font color="#990000">*</font>x<font color="#990000">,</font> state<font color="#990000">[</font><font color="#993399">2</font><font color="#990000">]</font> <font color="#990000">+</font> symbol<font color="#990000">*</font>y<font color="#990000">,</font> state<font color="#990000">[</font><font color="#993399">3</font><font color="#990000">]</font> <font color="#990000">-</font> symbol<font color="#990000">*</font>y<font color="#990000">,</font> <font color="#993399">1</font> <font color="#990000">-</font> state<font color="#990000">[</font><font color="#993399">4</font><font color="#990000">]</font><font color="#990000">)</font>
					<strong><font color="#0000ff">if</font></strong> self<font color="#990000">.</font><strong><font color="#000000">check</font></strong><font color="#990000">(</font>new<font color="#990000">)</font><font color="#990000">:</font>
						result<font color="#990000">.</font><strong><font color="#000000">append</font></strong><font color="#990000">(</font><font color="#990000">(</font>action<font color="#990000">,</font> new<font color="#990000">)</font><font color="#990000">)</font>
						action <font color="#990000">=</font> action <font color="#990000">+</font> <font color="#993399">1</font>
		self<font color="#990000">.</font>nodenum <font color="#990000">=</font> self<font color="#990000">.</font>nodenum <font color="#990000">+</font> action
		<strong><font color="#0000ff">print</font></strong> result
		<strong><font color="#0000ff">return</font></strong> result

	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">check</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> state<font color="#990000">)</font><font color="#990000">:</font>
		<strong><font color="#0000ff">for</font></strong> x <strong><font color="#0000ff">in</font></strong> state<font color="#990000">[</font><font color="#990000">:</font><font color="#990000">-</font><font color="#993399">1</font><font color="#990000">]</font><font color="#990000">:</font>
			<strong><font color="#0000ff">if</font></strong> x<font color="#990000">&lt;</font><font color="#993399">0</font><font color="#990000">:</font>
				<strong><font color="#0000ff">return</font></strong> False<font color="#990000">;</font>

		<strong><font color="#0000ff">if</font></strong> state<font color="#990000">[</font><font color="#993399">0</font><font color="#990000">]</font><font color="#990000">!</font><font color="#990000">=</font><font color="#993399">0</font> <strong><font color="#0000ff">and</font></strong> state<font color="#990000">[</font><font color="#993399">0</font><font color="#990000">]</font> <font color="#990000">&lt;</font> state<font color="#990000">[</font><font color="#993399">2</font><font color="#990000">]</font><font color="#990000">:</font> <strong><font color="#0000ff">return</font></strong> False<font color="#990000">;</font>
		<strong><font color="#0000ff">if</font></strong> state<font color="#990000">[</font><font color="#993399">1</font><font color="#990000">]</font><font color="#990000">!</font><font color="#990000">=</font><font color="#993399">0</font> <strong><font color="#0000ff">and</font></strong> state<font color="#990000">[</font><font color="#993399">1</font><font color="#990000">]</font> <font color="#990000">&lt;</font> state<font color="#990000">[</font><font color="#993399">3</font><font color="#990000">]</font><font color="#990000">:</font> <strong><font color="#0000ff">return</font></strong> False<font color="#990000">;</font>

		<strong><font color="#0000ff">return</font></strong> True

	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">goal_test</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> state<font color="#990000">)</font><font color="#990000">:</font>
		<strong><font color="#0000ff">if</font></strong> state<font color="#990000">[</font><font color="#993399">0</font><font color="#990000">]</font> <font color="#990000">=</font><font color="#990000">=</font> <font color="#993399">0</font> <strong><font color="#0000ff">and</font></strong> state<font color="#990000">[</font><font color="#993399">1</font><font color="#990000">]</font> <font color="#990000">=</font><font color="#990000">=</font> self<font color="#990000">.</font>N <strong><font color="#0000ff">and</font></strong> state<font color="#990000">[</font><font color="#993399">2</font><font color="#990000">]</font> <font color="#990000">=</font><font color="#990000">=</font> <font color="#993399">0</font> <strong><font color="#0000ff">and</font></strong> state<font color="#990000">[</font><font color="#993399">3</font><font color="#990000">]</font> <font color="#990000">=</font><font color="#990000">=</font> self<font color="#990000">.</font>N <strong><font color="#0000ff">and</font></strong> state<font color="#990000">[</font><font color="#993399">4</font><font color="#990000">]</font> <font color="#990000">=</font><font color="#990000">=</font><font color="#993399">1</font><font color="#990000">:</font>
			<strong><font color="#0000ff">print</font></strong> state
			<strong><font color="#0000ff">return</font></strong> True
		<strong><font color="#0000ff">return</font></strong> False<font color="#990000">;</font>

	<strong><font color="#0000ff">def</font></strong> <strong><font color="#000000">h</font></strong><font color="#990000">(</font>self<font color="#990000">,</font> node<font color="#990000">)</font><font color="#990000">:</font>
		<strong><font color="#0000ff">return</font></strong> <font color="#993399">0</font>
		state<font color="#990000">=</font>node<font color="#990000">.</font>state
		<strong><font color="#0000ff">return</font></strong> state<font color="#990000">[</font><font color="#993399">0</font><font color="#990000">]</font>

<strong><font color="#0000ff">if</font></strong> <font color="#990000">(</font>__name__<font color="#990000">=</font><font color="#990000">=</font><font color="#ff0000">"__main__"</font><font color="#990000">)</font><font color="#990000">:</font>

	state<font color="#990000">=</font><font color="#990000">[</font><font color="#993399">3</font><font color="#990000">,</font> <font color="#993399">0</font><font color="#990000">,</font> <font color="#993399">3</font><font color="#990000">,</font> <font color="#993399">0</font><font color="#990000">,</font> <font color="#993399">0</font><font color="#990000">]</font>

	instance <font color="#990000">=</font> <strong><font color="#000000">Boat</font></strong><font color="#990000">(</font>state<font color="#990000">)</font>
<em><font color="#9a1900">#	breadth_first_tree_search(instance)</font></em>
<em><font color="#9a1900">#	depth_first_tree_search(instance)</font></em>
<em><font color="#9a1900">#	breadth_first_graph_search(instance)</font></em>
<em><font color="#9a1900">#	depth_first_graph_search(instance)</font></em>
	<strong><font color="#000000">astar_search</font></strong><font color="#990000">(</font>instance<font color="#990000">,</font> instance<font color="#990000">.</font>h<font color="#990000">)</font>
	<strong><font color="#0000ff">print</font></strong> instance<font color="#990000">.</font>nodenum</tt></pre>
<p>BTW, if you need to highlight your source code  and convert it to HTML for example, one of the handy program is GNU <a href="http://www.gnu.org/software/src-highlite/" target="_blank">source-highlight</a>. I really love this.</p>
<div id="google_plus_one"><g:plusone></g:plusone></div>]]></content:encoded>
			<wfw:commentRss>http://blog.youxu.info/2007/10/04/a-practical-guide-to-the-aima-python-code-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

