2013年1月29日 星期二

Design Pattern

最近小弱弱版主在看設計模式(design pattern)相關的書,寫一下我對它的感想。

我認為design pattern中相當重要的是繼承和polymorphism的概念:
繼承讓我們能定義一個基礎的型別,然後依據不同類型的物件,都繼承自這個基礎型別
Polymorphism則允許我們利用基礎型別的pointer,依據執行時指向的物件來取用它的資料。

從design pattern來看,Polymorphism有兩個最重要的功能:
1. 也就是上面提過的,是在執行期決定要執行哪個function,只要用父代的pointer去access繼承產生的子代,就可以視生成哪個物件來取用它的function,這也是一般教polymorphism時會提到最基本的用處,相信設計師都很清楚了。
2. 第二個功能延伸自第一個,利用polymorphism給予我們執行期時的彈性,延伸出來的是,在設計、修改時保有彈性(也就是Design Pattern),把每個不相干的部分給分開,讓我們不必要每次要新增功能、新增新的物件時,都要進到Implementation的層次做修改,浪費許多時間在尋找該加上新功能的地方;另外也能減少增加新東西時,因為相依關係而要重新編譯的部分。
事實上我認為第二個功能的重要性遠高於第一項,設計的彈性增進工作效率,才能將Object oriented的火力全面發揮出來。

說個自己想,沒什麼用的例子:
比如說我們要寫個選角色的程式好了,每個角色都有一個主要的招式master spark之類
所以說,最簡單的寫法就先設定一個基礎的角色:class character,內含一個main_spell()
然後各個角色繼承這個character.h,定義自己的main_spell()裡面要幹什麼,這時候所有角色的介面就一致了,可以用一個character的pointer來操作每一個角色的功能。
但這樣做其實不夠好,如果今天我們希望有些角色的main_spell不要動作怎麼辦?然後每個人招式又都不一樣?
我們可以打開每個角色的原始碼,然後重載(overload, 這個翻譯=w=)main_spell()
可是如果我們要加上10個角色呢?
所以Design Pattern就會要求,不止character,連main_spell也要是一個base class,不同的招式則是繼承它後修改,character則包含一個main_spell的pointer,用polymorphism的方式取得不同招式;如此一來,可以很方便的加上新的main_spell,只要新增main_spell的class即可,在character的介面卻完全不需要更動, 在維護跟更新上會更有效率。

這個composition over inheritance應該算是最基本的design pattern的概念了,Design Pattern所教的,就是過去神級的設計師,針對許多設計上的問題提出適當的解決方案(雖然感覺就是愈會變動的地方就會加上更多虛擬層,或是愈切愈細),據說在STL裡面用上許多Design Pattern,如果小弱弱板主學有心得再上來獻醜。

參考資料:
1. Head First Design Pattern:
http://shop.oreilly.com/product/9780596007126.do
會用google的可以在後面加上pdf
2. http://sourcemaking.com/design_patterns
包山包海的Java/C++ source code

2012年12月14日 星期五

使用python自動回應php網頁

一、緣起:

這篇文的緣起是這樣的:修了一門課要交作業,要從server上把資料下載下來,剖析資料之後建立模型,把模型回傳給server,server會再產生資料。
以上的上傳下載要重複幾次,server的介面是利用php寫的。
這時候又回到我的哲學了:Working hard, after you know you are working smart.
手動下載、建模型、上傳,這並不是個smart的工作方式其一:來回數次用人做本來就慢;其二:也是最重要的一點,人做容易出錯,出錯就會GG要重做。Smart的工作方式不應該是這樣。


二、解決方案:

經過一些調查,我使用的是python urllib module,這是個超完整的python web module,於是就用這個來寫寫看。

問題一:用python來取得 html?
這部分urllib老早就寫好了,用如下的code,下面一行就可以把整個html以bytes的方式取出來: html = urllib.request.urlopen(hw_url).read()
如果要寫入檔案,在開檔的時候指定為'wb'就可以直接將html 寫到檔案中而不怕格式錯誤。 否則就要呼叫.decode(“utf-8”)的方式先轉換html的格式。
針對form filling的部分也有相對應的方式,可以用下面的方式把POST的訊息編碼,在urlopen的時候附加在後面。
data = {}
data['id'] = ID
form_data = urllib.parse.urlencode(data)
form_data = form_data.encode('utf-8') # data should be bytes
response = urllib.request.urlopen(php_url, form_data)
得到是相同可以用read()取得資料的方式,實地驗證過,會得到一個相同的html file。

問題二:取得最新的資料 - 使用正規表示法:
現在有了取得的html檔之後,要怎麼找出其中的連結? 這裡用上了regular expression module re的方式,這大概是地表上最強大的字串比對工具。 該網頁中的檔案下載連結類似這樣的格式
<a href=\'LOL/XD.txt\'>
只要parse <a href>的標籤,很容易就能找到所有的連結檔了
links = re.findall(“<a\s+href\s*=\s*'(.*)'”, data, re.DOTALL)\
其中()就是我們要尋找的目標,會被存入links之中,成為一個list object,取出最後一個連結,就是我們要的最新版本的檔案了。
另一方面,當使用者要使用這個程式時,會需要輸入他們的學號以供使用,這部分也是使用re module來進行檢查:
re.match(“\s*[A-Za-z][0-9]{7,7}\s*”, string)
不match的話就會回傳None,讓程式再進行一次問話。

問題三:如何執行本地程式?
這個倒比較簡單,使用python subprocess即可簡單完成:
command = "./{0}".format(program_name)
 stdout = subprocess.check_output(command.split())

問題四:如何透過php上傳檔案? 這地方問題就頭大了,查了很久一直不知道該怎麼寫比較好。後來是經強者我同學的提示,用的解決方案是httplib的解決方式: http://stackoverflow.com/questions/1270518/python-standard-library-to-post-multipart-form-data-encoded-data
很有趣的是,httplib的運作是先讀入根目錄,再由selector去要求根目錄下的某個檔案。
fields的部分為二元tuple組成的table,tuple前都為要填入form的name attribute,請愛用「觀看原始碼」自行找出對應的name attribute;
後者為要填入的值,例如fields = [(“name”,”yodalee”),(“nickname”,”garbage”)]
files的部分則是三元的tuple,依序為form的name attribute、filename、file的binary;第三個用open(file, 'rb')傳入即可;例如files = [(“model”, “test.txt”, open(“test.txt”, “rb”))] 

當個例子的code如下:
fields = [("id",ID), ("model_submit","")]
files = [("model", filename, open(filename, "rb").read())]

content_type, body = encode_multipart_formdata(fields, files)
h = httplib.HTTP(host)
h.putrequest('POST', selector)
h.putheader('content-type', content_type)
h.putheader('content-length', str(len(body)))
h.endheaders()
h.send(body)
errcode, errmsg, headers = h.getreply()
return h.file.read()
在id的欄位填入ID,model_submit欄位填入空白。
檔案則上傳filename所指的檔案。
上傳檔案,並取得結果存入h之中。

三、結論:

我只需要下個指令,就能把作業所有需要的檔案都準備完成,打包一下,作業就被秒殺了。雖然說我寫python code的時間其實遠超過我手動執行的時間,但整體而言輕鬆很多,這才是working smart!


 四、參考資料:

python urllib manual:
http://docs.python.org/3/howto/urllib2.html
httplib upload files(answer 2):
http://stackoverflow.com/questions/1270518/python-standard-library-to-post-multipart-form-data-encoded-data


五、致謝:

有關python httplib的使用,感謝AZ Huang同學的提點。
作業的部分,感謝Godgodmouse同學的指導。

2012年11月25日 星期日

將sonnet檔轉換到virtuoso上

做高頻電路討厭的就是,頻率太高的情況下,寄生的電容電感會在電路各處藏汙納垢(XD)。
所以在設計的過程,就需要跑很多電磁模擬,把這些寄生的效應一併考慮到模擬之中。
(會吃你一堆電腦的記憶體跟花一堆時間,這也是我為什麼有時間打這篇文章的原因,哈哈)
麻煩就在於,每次在電磁模擬軟體(實驗室用Sonnet)上畫完架構,然後開始跑,確定結果沒錯之後,又要在電路下線的軟體(實驗室用Virtuoso)上畫一遍。
最近學到,該怎麼把sonnet上的檔案匯到virtuoso上面,在這裡記錄一下。

理論上,我們只要把sonnet檔案匯出到GDSII檔,這是IC layout通用格式,幾乎所有的工具都支援;之後再從virtuoso讀入GDSII檔案即可。
遇到的麻煩是,在進行電磁模擬時,我們會在sonnet裡面建好電路一層一層的架構,但Virtuoso的環境卻是依所用的製程而定,它完全看不懂我們是在講什麼?
所以如果直接匯入的話,就會變成有些層virtuoso不知道該對應給誰,變得完全無法編輯,總之會出現各式各樣的問題。
幸好Virtuoso並沒有這麼笨,在匯入檔案的選項中,可以自行指定層與層的Map file,透過這個,理當能「無損的」將sonnet檔案匯入virtuoso中。

1. sonnet to GDSII:
在sonnet中,是將電路板切成一層一層不同的介質,然後可以在每層介質中填入金屬,去摸擬其中的電磁效應,我們要的就是這金屬的pattern。
下面是一個sonnet層數設定的截圖,從最上面的空氣……到最底層的substrate

合理的推斷,GDSII也是將一層一層的資料給記錄下來,但要怎麼知道?
我用的是開源的klayout打開gds下去看,得到如下的畫面:

發現到sonnet轉gds的規則很簡單,原本在sonnet設在第幾層的金屬,就會被轉到gds第幾層;很可惜的,sonnet中層與層間連接的via的資訊全都消失了,不過很多金屬不用重畫還是可以省下很多時間。

 2. GDSII to Virtuoso:
有了上面的資料之後,再來就是編寫map file: 一個map file 的格式如下:
#Cadence layer name  Cadence layer purpose Stream layer number Stream data type
#
TopMetal2 drawing 0-63 0-63

每一行分為四個子資料,分別是:在此製程中的某層的名稱;該層的用途;對應在stream檔中的層數;該層的資料。
像上面這種寫法,會把0-63層的資料都變成TopMetal2。
purpose的部分,大概有drawing, pin, net三種可以選擇,但從sonnet過來的話大概都是要要轉成drawing的。
stream layer number就是方才用klayout看到的layer編號;stream data type這部分則不是很清楚,但sonnet轉出來好像也不會特別去設定。
根據上面的轉出來的資料,可以自行編寫對應的map,data type不清楚就用0-63全部截下來:
#Cadence layer name  Cadence layer purpose Stream layer number Stream data type
#
TopMetal2 drawing 2 0-63
TopMetal1 drawing 3 0-63
MIM drawing 4 0-63
Metal5 drawing 6 0-63
Metal1 drawing 10 0-63
這樣各層就能夠轉換成功了:


不過另一方面,據說從sonnet匯入virtuoso時,有機會發生一些off-grid的問題,這就是一時之間無法解決的問題了。

結論:
這篇介紹了如何將電磁模擬軟體Sonnet上的繪圖,直接轉換到Cadence Virtuoso上面,我很喜歡 「work hard, after you know you are working smart」類似的話
如果可以直接匯入圖形(work smart),就不要花時間重畫(work hard)了。
理論上如果你用的是Sonnect V13以上的話,其實Sonnet已經含有和Virtuoso的介面了。 http://www.sonnetsoftware.com/products/sonnet-suites/ef_translators_cvbridge.html

參考資料:
1. GDSII format description: http://www.buchanan1.net/stream_description.shtml
2. Layermap format description:
http://www-bsac.eecs.berkeley.edu/~cadence/tools/layermap.html
3. open source gds editor, klayout:
http://www.klayout.de/

2012年11月16日 星期五

放大器的級間穩定

做多級的RF的放大器時,除了看一般的stability factor K值外,還需要去測試電路每級放大器的級間穩定。
實驗室一直遵照學長流傳下來的投影片:將電路從中切開,一邊看stability circle,另一邊看ADS裡面的「Map1 circle」跟「Map2 circle」這個東西,然後看看兩個圓有沒有相交在一起,可是這個Map 1/2 circle是啥鬼東西?極間穩定又是什麼?

1. 極間穩定的意義:


先考慮上圖的模型,在一個主動的電晶體兩旁接上matching的電路,stability circle的定義是,在什麼樣的$\Gamma_L$(or $\Gamma_S$)下,會讓$\Gamma_{in}$(out) >1,在$\Gamma_{in}$(out) > 1時,電路幾乎確定會不穩定,將$\Gamma_{in}$(out)=1的邊線畫出來的圓,就是穩定圓(stability circle)。
電路設計完後,一定會看看stability factor K是否全頻帶都大於1,就是要確認電路整體的$\Gamma_{in}$(out)都在穩定的範圍內。
可是若我們把電路切開,這個模型就不適用了,前後接的不是被動的matching電路,這時候我們就要確保,前端的load stability circle,和向後端可能看到任何一點阻抗,都不會相交;否則很不巧的該阻抗出現,電路就不穩定了;這就是極間穩定背後的原理。

所以說map1/2 circle是啥鬼?從上面的定義來看,我認為它所畫的是:當source(load)呈現任何被動阻抗時(也就是實部小於一,落在smith chart上的任何阻抗),會在另一邊load(source)上呈現的阻抗。
實際用複數變換來驗證看看:
$\Gamma_{in} = w = \frac{a \Gamma_L+b}{c\Gamma_L+d}$
改換上式為下式,兩行的abcd並不是相同的:
$\Gamma_L = \frac{a \Gamma_{in}+b}{c \Gamma_{in}+d}$
a=1, b= $-S_{11}$, c= $S_{22}$, d= $-\Delta$
其中 $\Delta = S_{11}S_{22}-S_{12}S_{21}$
這個 $|\Gamma_L|=1$經轉換後會畫出一個圓,其圓心和半徑為:
$C_L = \frac{c^*d-a^*b}{a^2-c^2} = \frac{-S_{11}|S_{22}^2|+S_{12}S_{21}S_{22}^*+S_{11}}{1-|S22|^2} = S_{11}+\frac{S_{12}S_{21}S_{22}^*}{1-|S22|^2}$
$r = \frac{ad-bc}{a^2-c^2} = |\frac{S_{12}S_{21}}{1-|S22|^2}|$
若兩圓相交,就表示有load會讓$\Gamma_L$呈現某阻抗,而該阻抗會落在不穩定圓中,也就使電路在這級不穩定(新細明體:你死了Q_Q)

2. 實際資料:

Linux有問題先查manpage,ADS遇到鬼先問F1 help,結果help裡面解釋是這麼寫的:
Used in Small-signal S-parameter simulations: The function maps the set of terminations with unity magnitude at port 1 to port 2. The circles are defined by the loci of terminations on one port as seen at the other port. A source-mapping circle is created for each value of the swept variable(s). This measurement is supported for 2-port networks only.
大概的意思是一樣的,依著help的註解找到了計算的ael原始碼,下面是map2的原始碼:
defun map2_center_and_radius(sParam, center, radius)
{
    decl S12xS21 = sParam(1,2)*sParam(2,1);
    decl s11MagSq = pow(abs(sParam(1,1)),2);
     *center = sParam(2,2)+S12xS21*conj(sParam(1,1))/(1-s11MagSq);
     *radius = abs(S12xS21)/(1-s11MagSq);
}
可見所做的是以$S_{11}+\frac{S_{12}S_{21}S_{22}^*}{1-|S22|^2}$為圓心,$|\frac{S_{12}S_{21}}{1-|S22|^2}|$為半徑的圓,和我們所計算的結果相符。

附件:

如何在blogger裡面插入方程式?目前找到兩種解決方案
第一種是用這篇文章中所建議的方式:
http://www.codecogs.com/latex/integration/blogger/install.php
照著裡面的步驟做即可,不過它是將LaTeX轉成圖片,再替換掉原本的文字,所以很醜...
而且測試發現Firefox會當掉(媽的連IE都可以了…),原因不明。
第二種是現在的作法:
方法同上,但code是在下面這個blog裡面找到的
http://aishuxue.blogspot.tw/2012/01/latex-blogspot.html

<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js" type="text/javascript">
MathJax.Hub.Config({
 extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js"],
 jax: ["input/TeX", "output/HTML-CSS"],
 tex2jax: {
     inlineMath: [ ['$','$'], ["\\(","\\)"] ],
     displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
 },
 "HTML-CSS": { availableFonts: ["TeX"] }
});
</script>
這個結果超漂亮的啊!!!,實在太強了!
在chrome跟firefox裡面都可以用,IE我倒不知道,反正懶得理他。

致謝:

本篇文章感謝503實驗室強者我同學曾奕恩,以及強者我學長陳柏翰學長在複數變換方面的指導。

2012年11月13日 星期二

c++ static 修飾詞

最近寫基因演算法的project,有需要使用到C++ class的static variable,因為我之前這個東西怎麼寫都會出錯,這次好不容易在強者陳仕勳(GodGodMouse)的指導下成功寫出可以用的static,在這裡記錄一下怎麼使用C++的Static(是說這些文章也多到滿出來了)。

靜態物件static的標記包括:在主體程式中使用,在函式中使用,和在class中作為靜態資料使用。
總歸三種使用方式,都是要在程式的各處中使用共有的一份資料,下面針對三種使用方式,分別寫明使用方法及使用的時機: 

1. Main程式:

在global 的地方使用static,可以讓該變數由程式的全域變數變成檔案內的全域變數,使用static的全域變數幾乎永遠是好習慣,畢竟其他程式設計師在用你的程式時只想把你的程式當黑箱子,要是哪個全域變數名字相衝……那大概不是一兩個幹字可以解決的問題,例如下文中的debug變數,我每個檔案都想要有debug變數,這時就要加上static。
簡單的例子,我們幾個cpp檔裡面都有一個debug變數(總不能main裡的叫maindebug,gui裡的叫guidebug吧?),如果不加上static
//main.cpp
int debug  = 0; 
//src1.cpp
int debug  = 0; 
這樣在最後編譯的時候,g++ main.o src1.o的階段,就會回傳錯誤,因為debug在這裡被重複定義。 因此,請為全域變數加上static。
Static int debug = 0
或者,與static相對的就是extern,宣告變數是在別的檔案裡有定義,這時候不能再給初始值(因為初始值是從別的檔案來的):
extern char* filename;

2. 在函數裡使用:

在函數裡加上static的變數,不同於一般的變數「在函數執行時起始,於函數終結時清除」,static變數在程式一執行時即被宣告。我想這個已經芭樂到不能再芭樂的地步了,例子也不勝枚舉,如果我們要輸出某函數被call幾次,請愛用static。
Void function(){
 static int i=0;
 cout << ++i << endl;
}

3. 在class裡使用:

在class裡使用,其功用在於,這個class產生的任何一個object(or instance if you like),都可看到static的變數或函數。 比如說我project寫的基因演算法的程式,經由隨機產生了10000個子代,每個子代都要對某一筆測試資料進行處理,看看結果好不好;這時候當然不可能每一個子代都保留一份測試資料的副本(記憶體不用錢也不是這樣花的吧…),就要用static的方式保存資料,讓每個子代都能看到。
在class裡面用會複雜一點,假設現在有一個叫static_test的class,架構如下:
//static_test.h
class static_test { 
public:
    static int static_var;
    static void output();
    int i;
};
所以我們宣告了一個static的integer跟一個static 的function,在.h宣告中,大部分的東西是一樣的。
但在定義式裡,就有些不同,由於static物件在是class共有的一部分,宣告class物件時並不會初始化static的物件,因此在.cpp裡面第一件事就是先初始化static物件:
//static_test.cpp
int static_test::static_var;
要不要給初始值沒什麼關係,但這行指明:static_test中有一個static_var,不寫這行編譯時會出現undefined reference to static_var。 取用static物件時,也要用'::'指明:我要取用static_test的物件,例如:
cout << static_test::static_var << endl;
static_test::static_var = 10;
static function是類似的事情,每一個class都可以取用這個function,但static function裡面,只能用到static的member,因為它並非任何一個object的function,自然不能取用其中的內容,就如文中的output()不能取用 i 這個變數。
據說static member最常用的地方是統計目前程式中生成了幾個object,在contructor中對static member+1,destruct的時候-1,不過作者到目前還是沒遇到相關的場合,所以…就算了吧,能用就好。

 4. 致謝: 

本篇文章,感謝陳仕勳(GodGodMouse)強者的指導。