陳凱 上海市位育中學
歷史上,有些思想實驗借助邏輯悖論可以推導出令人信服的答案,如伽利略的重力思想實驗,有些思想實驗中的問題未能獲得被普遍認可的解答,但它卻成為一種能顯現出人的思維方式和局限的特殊工具。
《莊子·雜篇·天下》中提到的“一尺之捶,日取其半,萬世不竭”,可看作是一個歷史悠久的思想實驗。原文指出這是惠施的一個辯題,并說“辯者以此與惠施相應,終身無窮”。人總是能在頭腦的想象中將已經取半的捶繼續施加以取半的動作,南宋學者洪邁在《容齋隨筆》中認為:“雖為寓言,然此理固具。蓋但取其半,正碎為微塵,余半猶存,雖至于無窮可也。”持原子不可再分割觀點的辯者大概很難說明白,原子所占空間何以是不可再分而取半的。不過,這個“萬世不竭”的結論,常讓人內心產生出一種找不到終極原因的不安感,大概正是這種不安,使得惠施的辯題常辯不衰。直到現代物理學取得豐富的成果后,人們從微觀粒子行為的不確定性與概率特征來加以審視,才發現其實不能用是或否來判定“一尺之捶,日取其半,萬世不竭”的命題,與復雜的物理現象相比,落于二邊的邏輯思維在此處是蒼白無力的。
本文特意創設了這樣一個和計算思維有關的思想實驗:某A自認為運用了計算思維解決了某一個問題,如某個需要用枚舉法解決的問題,并且,觀察某A解決問題過程的某B從某A的行為判定,某A確確實實是運用了計算思維解決了這個問題,那么,假設在后續時間里,某A不斷地用同樣的方法解決同一類問題,如解決的都是那種能采用枚舉法來解決的問題,那么,是不是有理由懷疑,從某個時刻開始,某A不再是運用計算思維,而是依賴某種思維慣性在解決此類問題呢?
為行文方便,姑且將此自創的思想實驗稱為“褪色的計算思維”,如果將描述中的“計算思維”換成“邏輯思維”(這種替換仍然是思想實驗的一部分),即某A自認為且被他人評價為的確運用了邏輯思維解決了某一類問題,而在后續時間內,某A不斷遇見這些需要用邏輯思維解決的問題,在這里,似乎就可以說,某A每次解決問題,確實都是運用了邏輯思維。
從“褪色的計算思維”中可以看出這樣的問題,如果教師想要借助枚舉法的運用創設一個培養和評價計算思維能力的情境和任務,那就要弄明白,學生在面對多個需要借助枚舉法解決的問題時,在其不斷采用的思維方法中,究竟哪一種的確可以算作是運用了計算思維,顯然,不能輕易地說,只要采用了枚舉法解決問題就是運用了計算思維,當熟悉了枚舉法解決問題的過程后,就只需要拿出已有的應用了枚舉法的計算模型或程序代碼,運用邏輯思維改變其部分輸入數據和輸入形式,也一樣能解決問題。當某A利用計算思維解決了某一類問題,并且構建了解決問題的模式后,當以后再遇到同類型問題時,計算思維的運用是不必要的。那么,教師應當如何構建一個具有運用計算思維必要性的情境和任務呢?
有一個邏輯推理趣題是這樣的:某推理比賽的冠軍是A、B、C、D四位同學中的一位。至于誰是冠軍,A說:“不是我。”B說:“是C。”C說:“是D。”D說:“C說的不對。”其中三個人說的是真話,一個人說的是假話,那么到底誰是冠軍?
曾有教師在介紹用于計算思維培養的教學案例中提到過這個例子。顯然,學生可以通過枚舉的方法來判別誰是冠軍,在具體操作上,既可以逐個地按不同人說謊的情況進行枚舉,也可以逐個地按不同人是冠軍的情況進行枚舉,通過排除掉存在矛盾的情況,就能得出結論。如果圍繞這個案例對培養計算思維進行深入的思考,會引出許多疑惑。
疑惑一:不需要借助枚舉,單純依靠邏輯推理也能解決此問題:由于C和D的說法是矛盾的,所以,說假話的必然是兩者之一,然后,如果D說的是假話,則B說的也必然是假話,兩個說假話的情況與預設條件不符,所以只能是C說了假話。可見,不借助枚舉,也能解決問題。即便說,使用枚舉法解決問題體現了計算思維的運用(雖然筆者并不認同這一點),那么,這里其實存在著計算思維運用的必要性的問題。
疑惑二:枚舉是人類思維活動中常用的方法,如在圖書館的書架上找出所有的教材、找出某個范圍內符合某種特定條件的數字、用窮舉的方法構建一個九宮幻方等,所以這里的問題是,用到了枚舉法,就一定是運用了計算思維嗎?如果非要說人在利用枚舉進行邏輯歸納時就運用了計算思維,是不是有一種強行將人的思想降低到機器行為的嫌疑?這里存在計算思維的識別特征的問題,也就是說,要如何將計算思維的運用從人的一般思維的運用中凸顯出來。需要考慮當人在利用枚舉算法解決問題時,哪些行為是具有可分辨的運用計算思維的特征的。
疑惑三:假設某A在學習了基本的程序語法后,構造了某個算法或某個計算模型,借助枚舉法解決了問題。在這種情況下,認為某A的確運用了計算思維解決問題的判定大致是可以得到認可的,但如果有某B直接學習并大致記住了解決此問題的枚舉算法,并利用算法解決了此問題,能不能就此認為某B運用了計算思維解決了問題?似乎無法找到證據,認為某B不是依靠對語言的理解(ChatGPT能通過對語言的機器學習來編寫枚舉算法的程序,能認為ChatGPT運用了計算思維嗎?),或是邏輯推理,或是算法思維來解決了問題。這里存在計算思維運用如何判定和評價的問題。雖然一般認為算法思維是計算思維的一部分,但既然提出了計算思維的概念,就應當思考包含了邏輯思維、系統思維、算法思維的計算思維在整體上是如何發揮作用的。
教師在教學設計中,如果要落實計算思維培養的目標,就需要明確計算思維運用何以必要,計算思維運用的特征如何凸顯,計算思維運用如何判定和評價這些問題。為了解決這些問題,就有必要對情境和任務本身進行一定的改造。限于篇幅,本文重點討論計算思維運用何以必要這個問題。
不妨做這樣的嘗試:在教學情境中,任務切入的角度其實并不是怎樣解決“誰說假話”的問題,因為,利用枚舉法解決此問題,只是日常的邏輯思維的運用而已。相較而言更重要的是,要思考如何構建能實現枚舉法的模型,來解決“誰說假話”的問題。需要注意的是,利用枚舉法和構造實現枚舉法模型這兩者間是有區別的。
考慮要設計出某個機器,這個機器能解決部分推理問題,那么,討論機器如何借助并僅僅借助枚舉法解決一系列類似的推理問題,就顯現出“機器如何(半)通用性地解決問題”這個有價值的課題。當然,也要同時為其他解決方案預留出空間,如并行搜索、邏輯編程等。圍繞機器的行為展開設計而不是借助程序語言環境實現任務目標,就是為了避免學生僅通過語言規則來完成任務。在一項進行中的調查中發現,大部分教師更傾向于在算法和程序設計的教學單元培養計算思維,但在課時有限的情況下,學生通常只能做到學習和應用枚舉算法,而不是構建枚舉算法,而一旦學生基本掌握了枚舉算法,就不再有親自體驗構建枚舉算法的可能了。所以,更好的辦法是將培養計算思維的平臺拓展到信息從采集、編碼、處理到應用的整個過程中。
下面,是逐個地按不同人說謊的情況進行枚舉,借助涂色和邏輯推理尋求“誰是冠軍”答案的方法:繪制4*4的表格,圖1是列舉出A說謊且其他人不說謊時描述的情況,深綠色代表描述中某人是冠軍,淺黃色代表描述中某人不是冠軍,未涂色的表示情況不明。第一行是根據A說謊時的描述情況進行糾正后的涂色,第二、三、四行分別是根據B、C、D各人的描述進行涂色。可見,圖中有兩處矛盾,其一,第一、三列有兩處深綠色,說明有兩個冠軍,產生矛盾。其二,第四列同時有一處深綠色和一處淺黃色,說明某人既是冠軍又不是冠軍,從而產生矛盾。所以,A說謊且其他人不說謊的情況被排除了。接下來還要分別按B、C、D說謊的情況繪圖,這里就不一一展示了。

圖1 A說謊時的涂色
即便繪制完成如圖1所示的圖表,且根據圖表做出了A說謊時產生矛盾的推論,這個過程中也只有邏輯思維在起作用,計算思維在哪里呢?不妨更換一下研究角度,問某個機器到底應該如何判斷出這種矛盾。這時候就可能涌現出許多不同的解決方案,一種可行的方案是,將不同的顏色用二進制數碼加以表征,深綠色設置為“01”,淺黃色設置為“10”,白色設置為“00”。首先,縱向每列按位進行或運算操作,如果得到“11”,則表示存在矛盾。如果以上操作不存在矛盾,則縱向每列按位進行或運算操作,得到四個數值結果,如果存在多個“01”,則表示存在矛盾。
從上述解決方案中可以看出,雖然人能直觀看出矛盾所在,但為了讓機器判斷出矛盾是否存在,就需要構造出一種能夠讓機器實現判斷的方法,這些方法用到了二進制編碼和二進制邏輯運算,這正是運用計算機科學的基礎概念進行問題求解和系統設計。
這里存在一個疑惑,假設學生沒有學習過二進制編碼和運算,那么是否就無法運用計算思維來解決這道推理趣題?筆者認為,信息的編碼和表征可以有很多種方式,有些方式未必符合當前計算機最有效率的運行方式,但人的創造不應該被現代數字計算機這種已成型的計算裝置的工作模式所束縛,創造和想象應當首先不受物理限制,然后再考慮物理現實中的可行性,這個問題留待以后討論。
某個機器要能實現枚舉,那么它必然要能做到選取下一個的動作,利用程序語言,當然很容易實現“下一個”,如“for i in range(10):”這樣的語句自然就能從0枚舉到9。但和前文所述類似,用程序語言實現這樣的“下一個”,不必然運用了計算思維,只要足夠熟悉程序語言就能做到,“for i in range(10):”本身就可以看成是“從10的范圍內取出每個數字給i”的人類語言的描述。
仍然以“誰是冠軍”為例,圖2中列出了枚舉所得的所有四種涂色情況,這四種涂色都是由最左面的聽眾視角變換而來的,變換規律也很簡單,分別是第一、二、三、四行的顏色發生變化,如果該行存在深綠色則變為淺黃色,淺黃色則變為深綠色。

圖2 從聽眾視角涂色變換成四種枚舉所得的場景的涂色
從每一行中找到某種顏色進行變換這個動作,本身就是一種枚舉,也就是說,為了枚舉出每一種說謊的情況,首先要對每一行的每一種顏色進行枚舉,這個機器表象的枚舉現象和底層的枚舉動作其實是不一致的,底層的動作支撐了表象中“下一個”動作的產生。底層的枚舉成為高層的實現枚舉的計算模型中的一個組成部分,這里再來看“運用計算機科學的基礎概念去求解問題和系統設計”這句話,對于“運用計算機科學的基礎概念去求解問題”,一方面其有可能與“運用計算機科學的成果去求解問題”相混淆,另一方面有可能讓人停留于“運用計算機科學的基礎概念在概念層面而不是在計算裝置實施計算的層面解決問題”,但如果強調的是“運用計算機科學的基礎概念去設計一個系統來求解問題”,那就為什么樣的思維方式屬于計算思維的運用劃定了更精確的界限。
枚舉中的“下一步”的可行也隱含了更多低層的原因,那是因為按當前數字計算機的體系結構,讀寫數據的操作必須遵循一定的指令的順序,這在計算機實體結構的層面上揭示了在構建計算模型過程中計算思維運用的必要性,在本欄目往期文章《芯中之數—一種展示計算機系統架構工作原理的方法》中對此已有論述,這里不再展開。但如果跳出計算機實體結構的限制,許多計算模型具有并行計算的能力,如DNA計算、量子點計算等,利用這些計算模型實施枚舉,就不再有如何實現“下一步”的問題。
枚舉算法中的“下一步”如何才能停下來,是一個必須面對的問題,也是一個有趣的問題。在高級程序語言中,當循環全部執行完畢后,程序就停了下來,但這是因為有操作系統在管理著程序的運行,程序停下來了,操作系統卻并沒有停下來。假設不使用普通的計算機,而是用圖靈機來解決枚舉并將顏色進行變換的問題,如用十進制數1代表二進制數01,用十進制數2代表二進制數10,具體運行規則和運行初始和終止時的狀態如下頁圖3所示,則能發現,圖靈機預設了一個停止狀態,當讀寫頭遇見空格—也就是沒有任何顏色存在的格子時,圖靈機就停止運行,但它是怎么停下來的呢?當電路判斷到數據符合某種特定的狀態時,就執行電路自己斷開的動作,這當然是可行的。用函數的遞歸也能實現當枚舉任務完成后自動且自主停機,如果遞歸函數是一種純粹抽象的機器,那么遞歸函數就是其自身的操作系統—雖然現實中,人類構建的遞歸計算裝置都有其物質實體。

圖3 枚舉結束后會自己停機的圖靈機,上方是初始時的數據,下方是任務完成后的數據
考慮到有學生對函數遞歸工作過程的理解存在困難,可以思考這樣一個演示方案,假設存儲器里存儲的不僅是數據,也包含對讀寫頭下一步動作的指令,那么機器就不僅能自動根據指令匹配特定數據和替換,還能實現“下一步”動作和適時停機了。圖4是一個借助圖形化編程工具實現的枚舉和自動停機的演示,用表情符號代表機器讀寫頭,用方塊代表存儲器。在這個例子中,存儲器數據中的第一個值代表讀寫頭將要做的動作,0代表右移,1代表停機。而#號后的數據則代表真正的需要被判斷或被替換的數值。讀寫頭既從存儲器中讀取和寫入數據,也根據存儲器中的數據,來指示下一步將要做的動作。

圖4 用圖形化編程工具演示讀寫頭和存儲器的行為
