掃地機器人、遞歸與科普

掃地機器人

如何設計一個掃地機器人?

首先先搞清楚掃地機器人運行的抽象版,就是一個2D不隨機行走,走過的地方要標記為乾淨,乾淨到一定程度停止。從設計角度要考慮面向對象編程,設定初始值與運行停止條件。也就是說我們要定義一個2D棋盤並將其網格化,然後定義一個棋子在上面遊走。兩者的基本聯繫是坐標,所以從繼承的角度先定義坐標類型。圍繞坐標標記或替換寫出棋盤與棋子的類型,到時候調用就ok了。初始值與停止條件是解決實際問題必須考慮的,不能沒法初始化運行,更不能完全停不下來。定址演算法效率什麼的倒可以暫時放到後面去考慮或不考慮,讓高級語言編譯器代工。

坐標的屬性很簡單,給出x與y即可。同時可以給坐標的移動寫一個函數,下一步的坐標要通過現有速度與角度進行更新來得到新坐標。因為棋盤與棋子的行為不同,我們最好用不同的類型來區分並針對特殊的類型進行編程,例如平面就需要有標記是否被清潔的屬性而棋子則要有移動屬性。這兩個類型中都要繼承來自坐標的屬性。

先看平面類型,我們要對平面類型預定義長與寬,這樣就可以按照單位長寬設計網格了。之後要進行初始化,預設全部都是髒的,那麼所有網格都有個髒的屬性。反映到編程上就是做一個列表,先存儲所有的坐標點,這個列表要可更新。這只是初始狀態,然後設計一個函數,當給出一個坐標後去檢查是否在髒的列表之中:如果在,從列表中刪掉;不在,繼續。針對這個類型設計一個函數來返回乾淨坐標的比例,這個比例用來判定是否停止工作。同時,我們還面對一個大的初始化問題,那就是平面要可以給出一個隨機點讓棋子開始遊走。有了平面坐標,臟凈判斷並初始化後,還要抽象一個邊界,當隨機行走坐標跑到預定義之外要返回一個邏輯判斷,讓棋子自行決定如何進行下一步。

然後就是棋子類型了,棋子要做的就是繼承一個棋盤類型並定義一個速度,初始的速度直接用棋盤裡的隨機點函數生成,這樣可以保證不會一出生就跑到棋盤外的坐標上去。然後初始方向直接隨機,接下來就是如何行走了。很簡單,棋子所在點在單位時間已經乾淨了,直接調用坐標類型的移動函數進行移動,將初始化中的方向與速度放進去即可。但需要注意的是要調用前面棋盤類型中的函數對下一個點進行判斷,看是否撞牆了,撞了牆就改方向,直到不撞牆為止。然後就是停止條件,直接通過棋盤類型中是否乾淨的比例進行判斷,如果達到一定比例就別幹活了。

然後我們就可以寫一個模擬程序來看看結果了,輸入的參數包括房間大小、速度、行走方式及停止條件,程序可以返回一個估計時間來進行調試。對於行走方式而言,常見的一般就是撞牆變方向,也有比較瘋狂的每一步都變方向。當然這都是基於演算法的,如果基於其他感測信號,也可以寫出更有針對性的演算法例如髒的地方降低速度等來提高效果。這樣通過程序我們已經可以模擬一個棋子連續遍歷棋盤的過程了。也就是說這時候我們把這個程序跟參數輸給掃地機器人,它就可以打掃空房間了。

真實狀態的房間除了牆還有桌子腿什麼的,不過用上面的演算法也可以跑,就是慢點。一般會通過感測器感應房間大小,要是沒有也無所謂,第一天跑時間長點,把房型撞出來也不難。先預設一個1000平的大房間,然後跑,撞牆就在坐標上做標記,跑時間長點就可以記住房型了。然後我們可以設計內置一個優化演算法,對已經撞出來的房型路線進行路線優化,得到時間最短的那個。如果再高級點,可以對平時打掃需要較長時間的地方(此時要依賴感測器了)進行坐標標記,關鍵位置提高功率。然後軟體可以放到樹莓派這種東西上跑,外接上一個壓力感測器得到牆的信號,一個電機跟電池保障能動能掃地,最好有個判斷乾淨與否的光學感測器就夠了。作為搞分析化學的,我建議搞個拉曼順道定性測下污染物是什麼,小型化質譜也應該可以,現在不流行原位電離嗎,上一個就得了。這樣不但採集了室內灰塵,順道連污染物一併測完了,然後斷面研究或隊列研究隨便搞,發點健康類文章問題應該不會太大。咦,好像寫跑偏了。

上面可以看出對任務編程的思考方法,但就編程而言,遞歸思想是其獨立於其他思考方式的關鍵,理解這個可能有助於科研中把實際問題轉化成編程問題。

遞歸

總的來說,遞歸是一個很有意思的現象(致敬RS(看動漫是80後及以後顯著不同於70後及以前的特徵(上一代看連環畫比較多(優質的連環畫也很有意思(我又致敬了一遍(這也是一種遞歸(確切說是形式遞歸(這個名字是我瞎起的(這種寫法是致敬《蝸牛與水母》(劉易斯的作品都值得一讀(這裡又嵌套一個遞歸(也可以理解成《盜夢空間》里夢的結構,不過遞歸思想會額外包括自指與循環),自指關鍵詞就是前面的遞歸),《細胞生命的禮讚》非常棒)這本書有一篇科學散文就用了大量嵌套),嗯,我有時候會很嚴肅的胡說八道,別當真),真正的遞歸需要包括邏輯自指與循環,有沒有很眼熟),關鍵詞就是很有意思),嘗試下多層嵌套遞歸),人物線條非常流暢,可理解為國產版漫畫,或者說漫畫是日韓的連環畫),這個區分並不嚴格,但都是很流行的娛樂形式),特別是來自於周邊鄰居國家的產品),其實我並不認識他),不過你現在應該理解寫程序為什麼需要縮進了。

科普

用不同的思考模式看同一個問題的能力越來越重要了,具體到實驗科學,越來越多的期刊與審稿人要求用不同的方法驗證同一個問題。舉例來說,你看到期刊A上提出了一種微生物蛋白可以對某種生物過程進行調控,你很輕鬆的通過蛋白序列反推了基因序列,通過搜庫你發現在哺乳動物中也存在類似基因,但你並不確定是否有同樣的功能,你該怎麼驗證?

方案一,通過基因工程方法沉默小鼠體內這個基因,看相應功能是否受影響,你可以敲掉,也可以用iRNA技術,然後沿著中心法則從轉錄到蛋白到表型看變化。

方案二,對該蛋白進行空間建模,把底物或相互作用的分子也放到同一空間里進行熱力學與動力學分析,看看是否有變化,討論分子層次機制。

方案三,調查存在該功能缺陷的人群基因組、轉錄組、蛋白組與代謝組的數據,特異性去關注這個蛋白或基因的表達,看有沒有異常。

方案四,為存在功能異常的動物過表達這個基因,看能否好轉;或者為正常動物過表達,看有沒有副作用,也是基因工程手段。

方案五,我編不出來了。

總之,從觀察數據,工程實驗手段與分子模擬模擬等手段都可以來研究同一個問題,證據越多,結論越可信。目前一個現象是分析手段一直層出不窮,但相應的科學理論根基卻基本構建在原有的理論框架里,特別是教材,對於經典問題的新角度驗證是比較匱乏的。好像很多結論成了安全區,但從理論角度並不存在安全區。例如知乎里天天有人說劑量決定效應,這裡面經常暗含了濃度低就不用討論了,但其實很多物質毒性在高濃度反而不如低濃度大。既有的科學知識事實上是新發現最大的障礙,這裡面的重災區就是各種形式的科普。

當前的科普太偏重於知識的普及,對於科學方法及思考方式的宣傳是欠缺的(當然沒有一定知識基礎,方法是無從立足的)。很多的科學報道與論文解讀,包括之前我寫的,都存在一個問題,那就是為了讓更多人看懂而犧牲了複雜性,著重論述簡單的結論而忽略其中可能存在的錯誤,一句科學家說的就完活了。目前知識傳播是具有侵略性與快餐性的,快速大量的獲取新知並無錯誤,但不考慮其中的錯誤就好比只看收益不看風險的投資。但其實擁有一個複雜多樣的思考方式可能更有助於真正理解科學研究,只是,我也不知道除了被老闆、實驗與審稿人虐的經歷,還有其他方式讓人更好理解科研。


推薦閱讀:

TAG:编程 | 科普 | 递归 |