31 October, 2007

用 Runge-Kutta 法解微分方程

日前從圖書館借了一本書 From Calculus to Chaos ,這本書主要是在介紹 動態系統 的一些特性,附了很多例子, 其中第4章有介紹如何用 Runge Kutta 方法來求得微分方程的數值解, 方法是出乎我意料之外的簡單,於是找了一個例子來練習,考慮下面的 Duffing equation

Duffing_equation

為了用 Runge Kutta 方法,要先把上式改寫為

Duffing_equation_2

Duffing equation 是二階非線性時變微分方程,二階是因為 \ddot{x}, 非線性是因為 x^3,而時變是因為 cos \Omega t。我是用 Python 來寫,用 Matplotlib 來做繪圖的工作, 注意在安裝 Matplotlib 之前需先安裝 Numpy

chaos

所使用的參數是 k=0.05, A=7.5, \Omega=1, 上圖的曲線是 x 對 t 做圖,兩條曲線的初始條件 (x, y) 分別為 (3.003, 3) 跟 (3, 3), 即兩個初始條件的差別只在第一個元素,而且只差了 0.003,可是從上圖可知大概在 20 秒之後, 兩條曲線開始有明顯的差異,這就是混沌系統 ( chaotic system ) 的特性之一, 系統對於初始條件的變化非常敏感,初始條件的微小變動會造成系統動態的巨大改變。 程式碼如下: (我是用 GeSHi 做 syntax highlight,程式碼在 chaos.py )

from pylab import *
from math import cos

k = 0.05
Omega = 1
A = 7.5

def f(t, state):
     [x, d_x] = state
     y = d_x
     d_y = -k * d_x - x*x*x + A*cos(Omega*t)
     return array([y, d_y])

def Runge_Kutta(a, b, h, initial):
    z = []
    state = initial
    hh = h/2
    for t in arange(a, b+h, h):
         z.append(state[0])
         k1 = f(t, state)
         k2 = f(t+hh, state+hh*k1)
         k3 = f(t+hh, state+hh*k2)
         k4 = f(t+h,  state+h*k3)
         state += h/6 * (k1 + 2*k2 + 2*k3 + k4)
    return z

a = 0
b = 50
h = 0.01

z = Runge_Kutta(a, b, h, [3, 3])
y = Runge_Kutta(a, b, h, [3.003, 3])
t =  [i for i in arange(a, b+h, h)]

plot(t, z, t, y)
xlabel('t')
ylabel('x')
show()

程式碼很簡單,我只介紹兩個 Numpy 提供的函式,分別是 arange() 跟 array(), Python 內建 range() 的參數型態只能是整數,Numpy 提供的 arange() 則允許參數型態是浮點。 學過線性代數都知道,向量空間中最基本的兩個運算分別是純量乘法跟向量加法,比如

    2 [1, 2, 3] = [2, 4, 6]
    [1, 2, 3] + [1, 0, 1] = [2, 2, 4]

可是 Python 內建的 list 型態,並沒提供這兩種運算,但是如果是用 array() 所宣告的型態, 則可直接使用這兩種運算。 有了 Numpy 提供的 arange() 跟 array (),程式碼是不是看起來就跟 維基百科 所列的演算法相差無幾呢?這就是 Python 程式語言的迷人之處, 趕快來學 Python 吧!

註:我是在 Yukuan's Blog 發現 Matplotlib 這個好用的 Python 函式庫。

20 September, 2007

兩個英文單字:detail, infinite

最近要寫一篇 paper 投到 IFAC 2008, 需要用到一句話「至於更詳細的討論」,很直覺地就翻成 for a detail discussion,用 google 一查,覺得很奇怪, 怎麼才 534 項查詢結果,這句話應該很常用才對, 於是再查一下 detail 這個字,喔喔,原來 detail 不能當形容詞,所以這句話應該翻成 for a detailed discussion 才對,這次用 google 就可以查到 1,310,000 項查詢結果。

此外,還會用到「無限多個元素」這個詞,一樣很直覺地翻成 infinite elements,用 google 查詢的結果有 42,900 項,可是總覺得怪怪的, 查了 infinite 這個字是形容詞沒錯,意思是無限的、極大的,仔細一想,才發現我會錯意了, infinite 並沒有無限多個的意思。 後來腦中浮現了 infinitely many 這個形容詞,因為記得看過別人這樣寫, 用 google 查詢 infinitely many elements 的結果發現這才是正確的寫法。

29 August, 2007

阿公店盃接力賽

8月26日參加了阿公店盃接力賽, 一隊有 6 個人,每個人要跑 5 公里。 會參加比賽是因為吳先生的邀請, 擔任中油慢跑的外援。 之前沒有跑過外面的比賽, 只有參加過校內的比賽。 跑 5 公里我大概需要 20 分, 不過如果要參加比賽,我覺得至少要跑進 18 分內才夠水準, 有受過訓練的跑者成績大概在 16 分初左右。 我的練習方式是一個禮拜跑 4 天,一次跑操場 20 圈 (1圈400公尺), 練習的時間、分量都算很少, 不過,跑步對我來說主要是維持身體健康, 所以目前也沒有打算再增加練習的時間。

比賽地點在 隬陀國中 附近,用 urmap 畫的比賽 路線圖 測得的距離大概是 5 公里。 當天的天氣不錯,太陽不是很大,適合跑步。 我被排在第一棒,原因是年輕,起步可以衝, 下午 3:30 一起跑之後,就看到前一群人衝了出去, 不想落後領先集團太多,所以一開始就用了 8 成力, 這應該是錯誤的決定,跑了大概快一公里之後,速度就開始掉,呼吸已經跟不上了, 只好放慢,等到體力稍微回復之後,再提升速度,後來比賽就一直維持這樣的節奏, 中間大概有追過 5 個人,跑到最後 1 公里的時候,我的呼吸已經非常吃力, 總覺得終點好遠,最後是用意志力撐完的,終點前的 200 公尺也沒辦法加速, 吳先生幫我測得的成績是 19'09, 是我目前跑 5000 公尺的最佳成績, 同隊的隊友說,如果穿比賽用的鞋子,還可再快個 10 秒, 我穿的鞋子是練習用,拿來比賽的話會嫌太重。

最後我們這一隊拿到第 18 名,總共好像有 43 隊參加。 不得不提一下我的隊友,第 3 棒的吳先生,已經 60 多歲, 在有腳傷的情況下,還可以跑到 22 分多的成績, 第 5 棒的許先生,大概 50 多歲,居然可以跑到 19 分多, 只比我慢一點,實在厲害,只能用老當益壯來形容他們了, 不知道我到他們這個年紀的時候,5 公里可以在幾分鐘內完成。

參加這種多人的接力賽果然有趣, 隊友會替你加油打氣,還有提醒一些比賽的注意事項,讓人覺得很溫暖。 還有我發現我的基本動作還要再加強, 跨步的動作不是很穩定,導致體力流失的很快, 比賽一開始加速的時候,還沒體會到這點, 是到有點喘的時候,才發現大腿的擺動不是很自然。 但是參加比賽實在是好秏時間啊, 回家之後還需要一天的時間休息, 所以之後如果要參加比賽的話,我會再多考慮一下。 儘管如此,能夠參加這次的比賽,還是覺得很開心 :P

24 August, 2007

排列組合

昨天在寫程式的時候,遇到了一個問題,我想產生下面的輸出:

(1,1): 0000
(1,2): 1000
(1,3): 0100
(1,4): 1100
(2,1): 0010
(2,2): 1010
(2,3): 0110
(2,4): 1110
(3,1): 0001
(3,2): 1001
(3,3): 0101
(3,4): 1101
(4,1): 0011
(4,2): 1011
(4,3): 0111
(4,4): 1111

該怎麼做呢?

我的解法如下:

    int i, j;
    char s[] = "0000";
    int k1 = 0;

    for(i=1; i>=4; ++i)
    {
        for(j=1; j>=4; ++j)
        {
             int k2 = k1 % 4;
             int k3 = k1 % 8;
             int k4 = k1 % 16;

             s[0] = (k1 % 2 == 1) ? '1' : '0';
             s[1] = (k2 / 2 == 1) ? '1' : '0';
             s[2] = (k3 / 4 == 1) ? '1' : '0';
             s[3] = (k4 / 8 == 1) ? '1' : '0';

             printf("(%d,%d): %s\n", i, j, s);
             ++k1;
        }
    }

想法很簡單, 首先我令一個變數 k1,從 0 一直累加到 15。 第一欄要產生 01010101,只要用 k1 % 2 就可以達到這個目的 (% 是求餘數的意思), 第二欄要產生 00110011,週期是 4,所以只要用 k1 % 4,就可以產生 0123 這個序列, 然後要把 0123 變成 0011 的話,只要做除以 2 的動作就好了,第三欄第四欄就依此類推囉。

22 May, 2007

Desperado

DesperadoEagles 的一首英文老歌。日劇 華麗一族 拿這一首歌當插曲,我也是因為看了華麗一族才會去找這首歌的資料。 PS. 中英對照 連結

我愛夏卡爾

「我愛 夏卡爾」 這首歌的旋律是華爾滋, 這在流行歌曲中不多見, 而歌詞是在描寫期待著戀愛的女生的心情, 我覺得是一首很可愛的歌。

30 April, 2007

旋木

星期六在看超級星光大道,聽到袁惟仁跟參賽者潘裕文合唱旋木。 旋木是旋轉木馬的意思,歌詞中的主角就是旋轉木馬,我覺得很有創意。 這一首歌是 王菲 2003 年專輯「將愛」中的其中一首, 後來袁惟仁在專輯「 你不知道的我 」中也有演唱這首歌。

30 March, 2007

跑步記趣

今天是校慶完的第二天, 小腿的酸痛還沒有完全消除, 覺得是越野跑爬山路帶來的影響, 不過練習慢跑應該沒問題。 到操場的時間是下午 7:00 左右,跟之前的練習一樣,打算跑 20 圈。

一開始我就慢慢的跑,跑到第 5 圈後, 我注意第一道也有一個人在跑步, 其實之前跑的時候常常看到他, 他的速度不快, 跑步特色是喘氣聲很大, 他的跑步姿勢還可以, 只是手會向外面甩。 我想說他的速度不快, 就稍微加速超過他好了, 那知,我加速他也加速,似乎不想讓我超過他。 那時我也不想跑太快, 就以稍快的速度跟著他跑, 看他可以撐多久。

他的體重應該有 80kg 以上, 我從後面看他的腳步已經有些沉重, 代表這個速度對他來說應該是稍快。 這個速度對我來說不會喘,只是校慶後腳的疲勞還沒恢復, 覺得還是保守些好,於是就跟在他後面跑, 跑完 5 圈後,他突然跟我說他還剩半圈, 他已經跑了 25 圈。 這時我有點驚訝,我也不知道說些什麼好, 就跟他說加油。 這時我還剩 10 圈, 不過最後只跑了 8 圈, 因為已經覺得肌肉疲勞, 所以就提早結束了,反正來日方長。 最後的記錄是:

     9'26"73, 8'32"14, 9'17"18, 5'33"46

前三項是 5 圈的時間,而第四項是最後 3 圈的時間。 由記錄可知第 6~10 圈的確是跑太快了啊! 最後我在休息的時候,有一位約 50 歲的阿伯問我說「小弟,跑幾圈啊?」 我一聽有點傻眼,我已經 27 歲了 XD 他又問我是不是每天跑,因為他常常看到我, 我回說我是隔天跑,跑 20 圈左右, 他再問我是不是在跑馬拉松? 一般人似乎對馬拉松的距離不太清楚, 馬拉松的距離是 42.195 公里,400 公尺的操場要跑 105.5 圈啊, 我還未夠班。 我其實也常常看到他繞操場走,但只有看到背影。

29 March, 2007

校慶 - 環校越野跑

3 月 28 日是學校校慶, 照例環校越野跑應該是在前一天舉辦,而其它項目是在校慶當天舉辦, 可是今年居然把環校越野跑移到校慶當天比,而且時間還是早上 7:30, 關於這點我只能說 「要命」。 所幸 3000 公尺是下午 1:20 比,而不是上午。

環校越野跑的 路線 跟之前一樣。 為了參加環校越野跑, 上星期五做了一次測驗,那時成績是 18' 47 比上次測驗成績快了 1' 08, 而且相當接近上次比賽時的 成績, 所以我目前的實力應該比上一次強。 比賽前晚 1:00 就睡了 (平常大概會到 3:00 才睡), 早上 6:00 起來後,覺得精神還不差,狀況應該還可以。 擔心吃了早餐會肚子痛,所以比賽前沒有吃任何東西,只有喝水。 7:00 到了檢錄的地方,卻發現工作人員並沒把檢錄的東西事先準備好, 搞到比賽前幾分鐘都還有人在檢錄, 所幸這次比較早到,還有充足的時間可以做熱身。 7:00 的時候還沒有什麼陽光, 有微風吹,是個跑步的好天氣。

可能是因為比賽移到早上的原因, 參賽的人數不多, 所以所有的組別都一起出發。 一起跑後有 5 個人在我前面,3 個不認識, 有兩個對手是目前的我所無法超越的。 那時覺得呼吸不太順,可能是不習慣在早上跑步吧! 快要出操場時有一個粗框藍衣男,跑在我右邊, 好像要擋到我前面的路, 為了避免煞車再超過他的步驟, 我就說「借過」 (不太記得我當時是說什麼), 他也識趣地沒有靠過來 (只能說感恩)。 過了逸仙館後,只剩 3 個人在我前面, 跟我最接近的是穿紅白相間衣服的, 我發現他只有起跑稍快,後面速度就掉下來了。 過了進海科院的轉角時,我就超越他了。 此時,我前面只剩兩個人囉。 剛進入海科院兩棟大樓之間的道路時, 我看到上次第一名 (簡稱 A) 已經在跑上坡了, 而上次第二名 (簡稱 B) 大概離我 30 公尺左右。 記得上跑到這裡的時候是完全看不見 A, 而 B 已經在跑上坡了, 這表示我的速度應該有所提升吧!

接下來就是恐怖的爬坡。 海科上坡還不是很陡, 可是武嶺上坡就真得很陡, 最陡的地方估計有 30 度。 爬坡需要大量的氧氣, 所以即使速度放慢還是覺得很喘, 克服這點的方法就是增加自己的肺活量。 爬坡時我總是想著只要過了最高點就可以獲得喘息, 藉此來說服自己不停的跑。 不像第一次跑環校因為太喘而停下來, 這次速度雖然慢,還是「跑」完了這一段上坡。 不過目前是完全看不到前面二人的背影, 之後的下坡我就放輕鬆跑,也沒有刻意加速, 最後就以等速跑回終點。 最後的成績如下:

挑戰組 15' 16" 99 16' 36" 00 18' 02" 37
活力組 20' 56" 27 22' 20" 20 22' 21" 44
女生組 23' 14" 79 24' 57" 81 27' 52" 49

最後拿到第 3 名,比起上次 成績, 進步了 41 秒,自己覺得還算滿意。 我覺得比較誇張的是第一名居然進步了 55 秒之多 Orz... 跑完之後跟系上通訊組的周老師聊天 (活力組第一名就是周老師), 之前校慶的時候有聊過,不過這次聊得比較久, 大概是交換一下跑步的心得。 只要沒受傷, 每一次校慶他都會參加比賽,看不出已經 50 歲了, 3000 公尺居然可以在 13 分內跑完,實在另人佩服。 此外,他是一個很神奇的人, 頭髮長度總是維持在比光頭稍微長一點, 前兩年他跑 3000 公尺時居然沒有穿鞋子, 去年他有穿鞋子,但他說他的鞋子是 20 年前的 (驚)。

越野跑比完之後, 就回到實驗室洗澡休息, 10:30 吃了一個薯餅跟飯團當作午餐, 也順便吃完早上買的早餐,一瓶多多跟一片葡萄土司, 之後還是休息 (此時我的心跳大概是每分鐘 95 下,比正常心跳快了 30 下)。 腳的狀況還算正常, 只是小腿的肌肉有點緊, 右大腿肌肉的舊傷,還是老樣子, 有感覺可是還不致於影響正常跑步。 下午的比賽應該沒問題吧。

3000 公尺比賽在下午 1:30 開始, 一起跑我前面只有兩個人, 一個是無法超越的第一名, 另一個是他朋友 (簡稱 C),不過之前沒有看他參加過比賽。 (越野跑第二名沒有參加比賽,我覺得他應該不是中山的學生。) C 的第一圈還蠻快的,第二圈就被我追過了。 我參加校內 3000 公尺的經驗是,大概在第三圈後就可以知道對手的實力了, 3000 公尺比賽要跑操場 7.5 圈,通常第一圈可以看到很多人以接近自己極限的速度在跑, 可是要維持這種速度很恐怖,沒在練的人以這種速度跑個一圈頂多兩圈,就會受不了, 之後只能用走的。 一開始我的速度稍快,可能是每圈 1' 25 ~ 1' 29。 跑完第三圈時,我覺得有點渴,應該是賽前覺得今天天氣不會很熱,所以水灌得不夠多,失策! 為了避免水分流失,我是閉著嘴巴在跑,只用鼻子呼吸,這時候跑步開始變得很辛苦, 我完全不能加速,只能讓速度維持在一定的水準 (可能是在每圈 1' 29 ~ 1' 32 左右), 最後的 4,5,6,7 圈算是用撐的, 最後 50 公尺有小加速,不過成績可能不是很好,因為完全沒有加速的感覺啊! 最後成績如下:

學生男子組 9' 48" 99 11' 07" 36 12' 09" 24
大一男子組 11' 54" 66 12' 57" 46 12' 57" 71

我是第二名,成績是 11' 07 比上次 3000 公尺 進步了 11 秒。12' 48 是周老師的成績。

10 February, 2007

我相信

這首歌是台啤 2006 年的廣告曲,應我妹 yuju 要求,把這首歌的歌詞放上來了。

06 February, 2007

曾經太年輕

「曾經太年輕」是白色巨塔的片尾曲, 作詞是方文山, 方文山 曾寫了一篇網誌介紹這首歌的背景。 歌詞寫得很棒,言之有物,又不會太矯情。厲害的是有押韻, 而且歌詞內容還大致跟白色巨塔的劇情吻合。

主唱是 藍又時, 沒有在電視上看過她,應該還在等出道的機會吧。 她的聲音高亢而有力量,算是有特色的聲音。 不過「曾經太年輕」這首歌的音實在好高, 有好幾個段落連原唱都要用假音才能唱上去, 導致我在學的時候是一整個唱不上去 Orz

05 February, 2007

出塞曲

這首歌的歌詞出自詩人 席慕蓉 的「出塞曲」,聽過幾次之後大概就琅琅上口了, 我妹聽我唱過一次之後,居然也喜歡這首歌, 所以就把歌詞弄上來了。