201871030132-熊文婷 實驗三 結對項目—《D{0-1}KP 實例數據集算法實驗平台》項目報告


項目 內容
課程班級博客鏈接 https://edu.cnblogs.com/campus/xbsf/2018CST
這個作業要求鏈接 https://www.cnblogs.com/nwnu-daizh/p/14604444.html
我的課程學習目標 (1)對D{0-1}KP問題加深理解
(2)運用至少一門語言構造圖形用戶界面
(3)了解並熟悉遺傳算法
(4)在結對合作過程中獲得除知識外其他能力
這個作業在哪些方面幫助我實現學習目標 (1)在結對合作的過程中認識自我的不足,積極吸取他人的長處
(2)通過對不了解的知識內容進行學習,提升自己的編程能力的同時也對自我學習的要求有高層次要求
結隊方學號-姓名 於澤浩-201871030139
結對方本次博客作業鏈接 https://www.cnblogs.com/yuzehao/p/14652203.html
本項目Github的倉庫鏈接地址 https://github.com/xwt721/SoftwareProject

任務1:閱讀《現代軟件工程——構建之法》


第3章 軟件工程師的成長

3.2 軟件工程師的思維誤區

​ 在閱讀了《現代軟件工程——構建之法》第三章第二節時,首先介紹的例子是以工程師果凍和項目經理大牛之間的對話為例:木桶有洞怎么辦?修哇!怎么修?用粗麻繩堵住!繩子太粗怎么辦?砍短!刀太鈍怎么辦?磨刀!磨刀石太干怎么辦?用木桶取水!木桶有洞怎么辦?......如此便陷入死循環,出現了“分析麻痹”的現象。

分析麻痹:一種極端情況是想弄清楚所有細節、所有依賴關系之后再動手,心理上過於悲觀,不想修復問題,出來了問題都賴在相關問題上。分析太多,腿都麻了,沒發起步前進,故得名“分析麻痹”(Analysis Paralysis)

-- 引用《現代軟件工程——構建之法》3.2 軟件工程師的思維誤區(P53)

​ 其次介紹的例子是小飛的故事,小飛要騎自行車上自習,但是最終導致的結果是追着氂牛跑這就產生了“部分主次,想解決所有依賴問題”。拿例子來說,小飛上自習一定要騎自行車去嗎?大可不必!他可以不解決自行車沒氣的問題轉而選擇徒步去上自習。所以,這種解決問題真的可以”完美“達成與設定目標嗎?恐怕不是,而是會造成更多不必要的麻煩。

不分主次,想解決所有依賴問題:另一種極端是過於積極,想馬上動手修復所有主要和次要的依賴問題,然后就可以“完美地”達成最初設定的目標,而不是根據現有條件找到一個“足夠好”的方案。

-- 引用《現代軟件工程——構建之法》3.2 軟件工程師的思維誤區(P53)

​ 接着還是以小飛同學為例,在上學的時候小飛的雨傘就很小,因為雨傘很小導致小李拒絕和小飛共同打傘,但是小飛的初心是希望離小李更近,而小李卻覺得傘太小,所以沒答應。幾年后,誤會解除,小飛才恍然大悟“過早優化是一切煩惱的根源”。這個例子是告訴我們不要先入為主,自以為是,最終導致的結果卻是竹籃打水一場空。

過早優化:既然軟件是“軟”的,那它就有很大的可塑性,可以不斷改進。放眼望去,一個復雜的軟件似乎很多模塊都可以變得更好。一個工程師在寫程序的時候,經常容易在某一個局部問題上陷進去,花大量時間對其進行優化,無視這個模塊對全局的重要性,甚至還不知道這個“全局”是怎么樣的。這個毛病早就被歸納為“一切罪惡的根源”。

-- 引用《現代軟件工程——構建之法》3.2 軟件工程師的思維誤區(P54)

​ 最后一個例子不是以一個小故事剛展開,而是以侯寶林的經典相聲——《畫扇面》為例,《畫扇面》大概講的的內容是,甲買了一把白色扇子,乙幫忙畫,結果從美女->張飛->山水->全黑,在經歷了這些過程后,白扇子硬是變成了黑扇子。也就是說目標設定的過於宏大,並沒有考慮自己是否可以真正的完成,結果一不小心,最初的目標都無法完成,造成更大的損失。

​ 以《畫扇面》與“做軟件工程團隊項目”做對比,對項目的期望值原本很高,不考慮實際情況,導致最終什么也沒做出來,只能以寫PPT結尾,項目爛尾。所以在一開始的時候就應該定一個切合實際的目標,在完成這項目標過后再逐步求精,一步一步完成,做到“上不封頂,下要保底”。

過早擴大化/泛化( Premature Generalization):軟件的“軟”還表現在它可以擴展。在寫一個程序的時候,需要某個函數可以處理整數類型和字符串類型的信息,有的程序員往往靈光閃現——哎、能不能把類型抽象出來,讓這個函數處理所有可能的類型?這樣不就一勞永逸了么?有些軟件本來是解決一個特定環境下的具體問題。有的程序員一想,我們能不能做一個平台,處理所有類似的問題,這樣多好啊!這樣的前景的確美妙,程序員的確需要這樣的凌雲壯志,但是要了解必要性、難度和時機。“畫扇面”就是一個很好的例子。

-- 引用《現代軟件工程——構建之法》3.2 軟件工程師的思維誤區(P54)

3.3 軟件工程師的職業發展

人們對待職業的態度等級:

1.臨時的寄托或工作(Temporary Work)

​ 在大學里你會看到很多人選IT專業的原因和“熱愛”沒有什么關系,有些人是因為專業調劑來到這里,有些人是因為要拿一個文憑作為敲門磚(例如,跨專業考上軟件專業的研究生、然后計划以碩士的資格去考公務員),有些人是臨時找到這樣一份工作,並不打算做長久。他們處於低動力、低技能的狀態。

2.工作(Job)

​ 這就是一個能掙錢養家的營生、如果別的營生更賺錢、那就會跳到別的地方去。一些人留在這個職業里。只不過是因為他不會做別的。這些人會經常問“軟件開發做到35歲以后怎么辦”這樣的問題。當然,如果了解和體會了軟件開發的投入和回報的關系,這些人的心態會進步到下一個階段。

3.職業(Profession )

​ 在工作的基礎上,如果有足夠的職業道德和職業規划、那么工作就是一個“職業”。只有在這個層次上可以開始談有意義的“輿業發展”。職業人士對“30歲以后”、“35歲以后”都有一定的打算。

4,投身的事業( Commitment / vocation )

把軟件項目相關的目標作為長期的承諾,碰到困難也不退縮,一直堅持到完成任務。

5.理想的呼喚( Calling )

一些人覺得這是理想的呼喚,通過軟件可以改變世界,他們主動尋找機會,實現自己的理想。

-- 引用《現代軟件工程——構建之法》3.3 軟件工程師的職業發展(P57)

​ 對於專業是否是自己的寄托、工作、職業、想要投身的事業或者理想呼喚這個問題只有自己清楚,也只有自己能感受到,如何從中轉變也是依據自己的成長經歷、社會閱歷等方面,如果我們對職業有認真的態度,就能發現很多證明個人能力的方式。

3.4 技能的反面

​ 作者以自己小學五年級玩魔方為例,通過熟背口訣在當時的學生界很受歡迎並且稱得上“精通”。幾年過去后,雖然口訣還記得,但是在轉到最后一層魔方后卻想不起來口訣。也就是說,在玩魔方方面,作者只是簡單的記住口訣,並沒有真正的理解,這就導致了只能“獨立地還原一面,其他看口訣可搞定”。這還值得稱為“技能”嗎?

技能的反面是解決問題(Problem Solving)

-- 巴克斯頓

​ 對於巴克斯頓所說的問題,再結合例子,我的理解是:在某個人表現為不精通某項技能時候會考慮如何讓自己“精通”,這就涉及到了“解決問題”的過程,在解決的過程中又會涉及到先要解決最底層的問題,如果底層問題無法解決的話,那么如何解決更高層次的問題呢?“技能”與“精通”是一個相輔相成的兩個詞語,對於一個面試者來說,當他說他擁有某項技能,說明他對這項技能擁有很強的熟練程度,所以我建議在簡歷上還是不要在技能一欄中寫自己不熟練的活動內容。


第四章 兩人討論

4.1 代碼規范

​ 如何判斷一個代碼是“好”還是“不好”。如下圖所示代碼

-- 引用《現代軟件工程——構建之法》4.1 代碼規范(P69)

​ 讀者在看上圖所示代碼時會感覺讀不下去,這樣的代碼雖然機器可以識別,可以編譯並且執行,但是讀者在看的時候會感覺不太舒服,感覺很亂,這就要求在代碼風格、設計上面下功夫。

4.2 代碼風格規范

代碼風格規范包含縮進、行寬、括號、斷行與空白的{}行、分行、命名、下划線、大小寫、注釋。
  • 縮進

    如何縮進,縮進幾個空格?這些是需要統一的,一般用Tab鍵縮進4個空格。

  • 行寬

    行寬必須限制,但是以前有些文檔規定的80字符行寬太小了,現在時代不同了,可以限定為100字符。

  • 括號

    在復雜的條件表達式中,用括號清楚地表示邏輯優先級。

  • 程序的結構風格

1.最簡格式A

if (condition)  DoSomething();
else  DoSomethingElse();

2.斷行結構B

if (condition)
	DoSomething();
else
	DoSomethingElse();

3.用“{“和”}”來判斷程序的結構,改進的結構C

if (condition){
	DoSomething();
}else{
	DoSomethingElse();
}

4.“{”和“}”獨占一行結構D

if (condition)
{
	DoSomething();
}
else
{
	DoSomethingElse();
}
  • 分行

    不要把多條語句放在一行上,如:

a = 1; b = 2;  //bogus
if (fFoo) Bar();   //bogus

更嚴格地說,不要把多個變量定義在一行上,如:

Foo foo1, foo2;   //bogus
  • 命名

    變量命名一般要符合的規則是“看名知意”,也就是說看到這個變量的命名,就可以知道這個變量名是做什么的。

    命名的建議:

    • 在變量名中不要提到類型或其他語法方面的描述。例如一個表示全年假日的列表變量,不用寫arraylist0fHolidays,可以直接寫holidays;
    • 避免過多的描述。例如一個變量是游戲中最后出現的“大 boss”,不用寫theFinalBattleMostDangerousBossMonster,可以直接寫boss;
    • 如果信息可以從上下文中得到,那么此類信息就不必寫在變量名中。例如一個類叫EmployeeHealthRecord,它有一個員工姓名的變量,可以直接是“name”,而不必寫employeeName;
    • 避免可要可不要的修飾詞。例如state,data,value,engine,entity,instance,object,manager,可以問自己.如果在變量名中把這些字都去掉,程序會更加難懂么?如果答案是否定的,那么可以把這些修飾詞都去掉。
  • 下划線

    下划線用來分隔變量名字中的作用域標注和變量的語義,如:一個類型的成員變量通常用"m"表示,或者簡單地用一個下划線“_”來做前綴。移山公司規定下划線一般不用在其他方面。

  • 大小寫

    由多個單詞組成的變量名,如果全部都是小寫,很不易讀,一個簡單的解決方案就是用大小寫區分它們。

    Pascal——所有單詞的第一個字母都大寫。

    Camel——第一個單詞全部小寫,隨后單詞隨Pascal形式,這種方式也叫 lowerCamel。

    一個通用的做法是:所有的類型/類/函數名都用Pascal 形式,所有的變量都用Camel形式。類/類型/變量:名詞或組合名詞,如 Member 、ProductInfo等。

    函數則用動詞或動賓組合詞來表示、如l get/set 、RenderPage( )。

  • 注釋

    復雜的注釋應該放在函數頭,很多函數頭的注釋都用來解釋參數的類型等,如果程序正文已經能夠說明參數的類型in/out,就不要重復!

    注釋也要隨着程序的修改而不斷更新,一個誤導的(Misleading )注釋往往比沒有注釋更糟糕。另外,注釋(包括所有源代碼)應該只用ASCII字符,不要用中文或其他特殊字符,否則會極大地影響程序的可移植性。

    在現代編程環境中,程序編輯器可以設置各種美觀得體的字體,我們可以使用不同的顯示風格來表示程序的不同部分。

4.3 代碼設計規范

​ 不同的編程語言具有不同的設計規范,但是也有通用的原則。

  • 函數

    現代程序設計語言中的絕大部分功能,都在程序的函數( Function、Method )中實現。關於函數,最重要的原則是:只做一件事,並且要做好。

  • goto

    函數最好有單一的出口,為了達到這一目的,可以使用goto。只要有助於程序邏輯的清晰體現,什么方法都可以使用,包括 goto。

  • 錯誤處理

    當程序的主要功能實現后,一些程序員會樂觀地估計只需要另外20%的時間,給代碼加一些錯誤處理就大功告成了,但是這20%的工作往往需要全部項目80%的時間。

    • 參數處理
    • 斷言

4.4 代碼復審

名稱 形式 目的
自我復審 自己 vs. 自己 用同伴復審的標准來要求自己。不一定最有效,因為開發者對自己總是過於自信。如果能持之以恆,則對個人有很大好處
同伴復審 復審者 vs. 開發者 簡便易行
團隊復審 團隊 vs. 開發者 有比較嚴格的規定和流程,適用於關鍵的代碼、以及復審后不再更新的代碼覆蓋率高——有很多雙眼睛盯着程序,但效率可能不高(全體人員都要到會)

-- 引用《現代軟件工程——構建之法》4.4 代碼復審(P79)

4.5 結對編程

​ 結對編程是指在編程過程中由兩人組成一個團隊,對軟件項目進行分工編寫。結對編程目的是實現“1+1>2”的效果,每個人在各自獨立設計、實現軟件的過程中可能會犯錯,但是在結對編程的過程中通過交流和復審,程序各方面的質量提高,這樣可以節省很多修改和測試的時間。

4.6 兩人合作的不同階段和技巧

1.萌芽期間(Forming)

​ 這一階段由於兩人剛認識,有不同的期望值,彼此雙方並不了解,需要更多的磨合。

2.磨合階段(Storing)

​ 剛開始合作時,總會出現這樣那樣的情況,但是只有這樣才會加深彼此之間的認識。

3.規范階段(Norming)

​ 在經過了磨合階段后,成員之間主鍵合拍,許多意見和建議取得一致,並且配合緊密。

4.創造階段(Performing)

​ 在經過上述三個階段后,團隊成員之間可以達到合二為一的效果,但是並不是所有的合作都能達到這一階段,磨合太多后,可能進入“解體階段”。

5.解體階段(Deforming)

​ 由於在“磨合階段”一方無法接受另一方,導致失敗,只能散伙或找其他合作伙伴。

​ 在兩人合作期間,因為每個人都是一個獨立的個體,都有各自的意見和想法,那么在兩個人平等合作的情況下,如何影響對方,如何說服對方。

方式 簡介 邏輯/感情 推/拉 注釋
斷言(Assertion) 解釋這樣吧,聽我的,沒錯! 感情 推——主動推動同伴做某事 感情很強烈,適用於有充分信任的同伴。語音、語調、肢體語言都能幫助傳遞強烈的信息。
橋梁(Bridge) 能不能再給我講講你的理由...... 邏輯 拉——吸引對方,建立共識 給雙方充分條件互相了解
說服(Persuasion) 如果我們這樣做,根據我的分析,我們會有這樣的好處,a,b,c...... 邏輯 推——讓對方思考 有條理,建立在邏輯分析的基礎上。即使不能全部說服,對方也可能接受部分意見
吸引(Attraction) 你想過舒適的生活么?你想在家里發財么?加入我們的傳銷隊伍吧,幾個月后就可以有上萬元的收入...... 感情 拉——描述理想狀態,吸引對方加入 可以有效地傳遞信息,但是要注意信息的准確性。誇大的渲染會降低個人的可信度

-- 引用《現代軟件工程——構建之法》4.6.1 兩人的合作——如何影響對方(P90)


任務二:自由結對,對對方《實驗二》的項目成果進行評價

1、代碼復審核查表

(1)對結對方的博文進行閱讀和評論

  • 結對對象

    於澤浩

  • 評論內容

    • 結構方面

      1、我認為PSP內容應該放在任務2的內容中,因為任務2要求掌握PSP的流程,如果把個人PSP加到這部分會感覺結構更加完整。

      2、任務3中的文字太多,而且我個人覺得段落之間稍微空一點距離可能更容易讓讀者解讀。

    • 內容方面

      1、代碼展示部分建議放算法,並且注釋清楚放的這部分代碼是做什么用的。

      2、總結寫的較為完善,分點羅列不僅思路清晰,邏輯也清楚。

      3、從PSP的內容可以看出,計划完成需要的時間和實際完成需要的時間之間的時間差並不是很大,說明於澤浩同學時間管理能力較強,對時間的掌握和規划很准確。

(2)克隆結對方項目源碼到本地機器,閱讀並測試運行代碼

結對方姓名:於澤浩

結對方Github的倉庫鏈接:https://github.com/yuze-hao/OneProject/blob/main/背包問題.py

復審部分 提出問題 執行情況
概要部分 1)代碼符合需求和規格說明么?
2)代碼設計是否考慮周全?
3)代碼可讀性如何?
4)代碼容易維護么?
5)代碼的每一行都執行並檢查過了嗎?
1)代碼部分被分成了多個部分,代碼注釋稍顯周全;
2)因為代碼分模塊完成,所以我認為在代碼維護方面應該比較容易
3)代碼的可讀性稍顯困難,在較為復雜的代碼行后面沒有增加注釋
設計規范部分 1)設計是否遵從已知的設計模式或項目中常用的模式?
2)有沒有硬編碼或字符串/數字等存在?
3)代碼有沒有依賴於某一平台,是否會影響將來的移植(如Win32到 Win64 ) ?
4)開發者新寫的代碼能否用已有的Library/SDK/Framework中的功能實現?在本項目中是否存在類似的功能可以調用而不用全部重新實現?
5)有沒有無用的代碼可以清除?
1)設計較為遵從常用模式
2)有字符串和數字存在
3)開發者新寫的代碼無法用已有的Library/SDK/Framework中的功能實現
4)基本沒有無用代碼,但是有些代碼可以合並
代碼規范部分 修改的部分符合代碼標准和風格嗎? 修改的部分符合代碼標准和風格
具體代碼部分 1)有沒有對錯誤進行處理?對於調用的外部函數,是否檢查了返回值或處理了異常?
2)參數傳遞有無錯誤,字符串的長度是字節的長度還是字符(可能是單/雙字節)的長度,是以0開始計數還是以1開始計數?
3)邊界條件是如何處理的?switch語句的default分支是如何處理的?循環有沒有可能出現死循環?
4)有沒有使用斷言(Assert)來保證我們認為不變的條件真的得到滿足?
5)對資源的利用,是在哪里申請,在哪里釋放的?有無可能存在資源泄漏(內存、文件、各種GUI資源、數據庫訪問的連接,等等)?有沒有優化的空間?
6)數據結構中有沒有用不到的元素?
1)開發者對錯誤進行了處理,並且處理錯誤之后還進行了分析
2)字符串的長度是以0開始計數
3)循環沒有出現死循環
效能 1)代碼的效能( Performance )如何?最壞的情況是怎樣的?
2)代碼中,特別是循環中是否有明顯可優化的部分(C++中反復創建類,C# 中 string的操作是否能用StringBuilder來優化)?
3)對於系統和網絡的調用是否會超時?如何處理?
1)代碼最壞的情況是運行出錯,並且出現了“list index out of range”,列表參數溢出范圍
2)對於系統和網絡的調用可能會超時,因為在運用回溯算法的時候耗時較長
可讀性 代碼可讀性如何?有沒有足夠的注釋? 代碼可讀性較好,有足夠的注釋
可測試性 代碼是否需要更新或創建新的單元測試? 不需要

-- 引用《現代軟件工程—構建之法》4.4.3 代碼復審的核查表(P82)


任務三:采用兩人結對編程方式,設計開發一款D{0-1}KP 實例數據集算法

需求分析陳述

​ 目前,求解折扣{0-1}背 包 問 題(D{0-1}KP)的主要算法是基於動態規划的具有偽多項式時間的確定性算法,當D{0-1}KP實例中各項的價值系數與重量系數在大范圍內取值時缺乏實用性。折扣{0-1}背包問題(Discounted {0-1} Knapsack Problem,D{0-1}KP)是比0-1背包還要難以求解的NP-hard問題。提出了一種求解D{0-1}KP的新遺傳算法GADKP。

(1)平台基礎功能:實驗二 任務3

​ 實驗二任務3的鏈接:https://www.cnblogs.com/wentingxiong/p/14599087.html

(2)D{0-1}KP 實例數據集需存儲在數據庫

​ 利用MySQL軟件與Python數據庫連接,將實驗二的數據集中的一部分加入數據庫,如圖所示。

數據庫連接

config = {
    'host': 'localhost',
    'port': 3307,
    'user': 'root',
    'password': '815490',
    'db': 'dk',
    'charset': 'utf8',
    'cursorclass': pymysql.cursors.DictCursor,
}

connection = pymysql.connect(**config)
connection.autocommit(True)
cursor = connection.cursor()

def get_table_list():
    results=[]
    cursor.execute('show tables from dk;')
    query_result = cursor.fetchall()
    for i in query_result:
        results.append(i['Tables_in_dk'])
    return results

def get_data(sets_name):
    sql='select * from '+sets_name+';'
    cursor.execute(sql)
    query_result = cursor.fetchall()
    return query_result

(3)平台可動態嵌入任何一個有效的D{0-1}KP 實例求解算法,並保存算法實驗日志數據

​ 在實驗二的基礎上,加入實驗日志數據,文件命名為“月-日-年.txt”,如圖所示。

流程圖

回溯算法並剪枝

 def bound(self, k, caup):  # 計算上界函數,功能為剪枝
        ans = self.val
        while k < self.size and caup >= self.items[k].pack[2].weight:
            caup -= self.items[k].pack[2].weight
            ans += self.items[k].pack[2].profit
            k += 1
        if k < self.size:
            ans += self.items[k].pack[2].profit / self.items[k].pack[2].weight * caup
        return ans

    def Backtracking(self, k, i, caup):  # 回溯算法
        bound_val = self.bound(k + 2, caup)
        if k == self.size - 1:
            if self.max_val < self.val:
                self.max_val = self.val
                self.so_res = list.copy(self.so_tmp)
            return
        for j in range(3):
            if caup >= self.items[k + 1].pack[j].weight:
                self.val += self.items[k + 1].pack[j].profit
                self.so_tmp.append((k + 1, j))
                self.Backtracking(k + 1, j, caup - self.items[k + 1].pack[j].weight)
                self.so_tmp.pop()
                self.val -= self.items[k + 1].pack[j].profit
            if bound_val > self.max_val:
                self.Backtracking(k + 1, j, caup)

動態規划算法

def DP(self):  # 動態規划算法
        dp = [[[0 for k in range(self.cubage + 5)] for i in range(4)] for j in range(self.size + 5)]  # 三維dp數組
        for k in range(1, self.size + 1):
            for i in range(1, 4):
                for v in range(self.cubage + 1):
                    for j in range(1, 4):
                        dp[k][i][v] = max(dp[k][i][v], dp[k - 1][j][v])
                        if v >= self.items[k - 1].pack[i - 1].weight:
                            dp[k][i][v] = max(dp[k][i][v],dp[k - 1][j][v - self.items[k - 1].pack[i - 1].weight]+self.items[k - 1].pack[i - 1].profit)
                        self.max_val = max(self.max_val, dp[k][i][v])

(4)人機交互界面要求為GUI界面(WEB頁面、APP頁面都可)

​ 利用python自帶框架tkinter繪制GUI界面,如圖所示。

(5)查閱資料,設計遺傳算法求解D{0-1}KP,並利用此算法測試要求(3)

​ 參考文獻:

​ [1]吳聰聰,賀毅朝,趙建立.求解折扣{0-1}背包問題的新遺傳算法[J].計算機工程與應用,2020,56(07):57-66.

​ [2]楊洋,潘大志,劉益,譚代倫.折扣{0-1}背包問題的簡化新模型及遺傳算法求解[J].計算機應用,2019,39(03):656-662.
遺傳算法偽代碼,如下圖所示。

運行結果圖

核心代碼

def select(self):
        '''采用選擇概率和累積概率來做選擇,得出下一代種群(個數不變)
        對環境適應度高的個體,后代多,反之后代少,最后只剩下強者'''
        last_cho_feq = 0
        for i in range(0, population_size, 1):
            try:
                self._gatype[i].cho_feq = self._gatype[i].fitness / float(self.total_fitness) # 選擇概率
            except:
                # print('error', self.total_fitness)
                pass
            self._gatype[i].cum_feq = last_cho_feq + self._gatype[i].cho_feq # 累積概率
            last_cho_feq = self._gatype[i].cum_feq

        # _next = deepcopy(self._gatype)  # 下一代種群,參與到后續的交叉和變異
        _next = [GAType(self.obj_count) for x in range(0, population_size, 1)]
        for i in range(0, population_size, 1):
            choose_standard = random.randint(1, 100) / 100.0
            # print('choose_standard: %f' % choose_standard)
            if choose_standard < self._gatype[0].cum_feq: # 選出下一代種群
                _next[i] = self._gatype[0]
            else:
                for j in range(1, population_size, 1):
                    if self._gatype[j-1].cum_feq <= choose_standard < self._gatype[j].cum_feq:
                        _next[i] = self._gatype[j]
        self._gatype = deepcopy(_next)
        self.avoid_zero() # 全零是不可避免的

(6)附加功能:除(1)-(5)外的任意有效平台功能實現

​ 在問題(1)-(5)外的問題中,我們實現的其他功能有:

  • 計算不同算法運行的時間
  • 優化實驗二中文件讀取的功能

總結

​ 本次實驗是我結結實實的用三天時間完成的,第一次切實的體會到合作的重要性以及快樂感。在本次實驗中,我要特別感謝我的結對對象——於澤浩,我和他雖然已經不是第一次結對,但是每一次都會有不一樣的體驗,在這次實驗中,因為很多內容涉及到我們的知識盲區,所以我們的分工不是很明確,很多時候都是在一起做,一起討論,如下表所示。

成員姓名 討論日期 所做內容
熊文婷 2021.4.9 通過中國知網、萬方等網站查找關於遺傳算法資料
於澤浩 2021.4.10 設計GUI界面
熊文婷 2021.4.10 修改實驗二代碼,在此基礎上為創建圖形用戶界面、連接數據庫做准備
於澤浩 2021.4.11 設計遺傳算法偽代碼
熊文婷、於澤浩 2021.4.12 積極討論在單人工作期間遇到的問題,展示這段時間的實驗成果並且共同解決
熊文婷、於澤浩 2021.4.13 同上

​ 在單人工作時會遇到很多意外,比如數據庫軟件下載有問題、數據庫連接不上、設計的界面沒有達到預期的目標等等,但是當兩人見面后將彼此的問題告訴對方時,不僅僅可以獲得建議還能互相學習,共同進步。我們在解決這些問題時也讓其他的小伙伴幫我們拍了照片,如下所示。

  • 設計頁面

  • 討論圖1

  • 討論圖2

​ 所以我認為,當遇到“合適”的合作者時,工作的效率確實能達到1+1>2的效果,而這個“合適”取決於這個人與你的”胃口“是否相對。兩個人的共同努力才能最大程度的實現結對的真正意義和發揮結對的最大功效,讓我們的項目成果就是比那些沒有合作的同學完成度高。

結對PSP

任務內容 計划共完成的時間(min) 實際完成時間(min)
計划 30 40
結對成員認識 10 8
任務分工及初步討論 20 32
開發(預計三天完成) 490 590
圖形用戶界面設計 30 30
數據庫設計 60 60
實驗二代碼修改 130 140
代碼更改 120 170
遺產算法(查看資料) 60 60
遺傳算法傳算法(偽代碼編寫) 90 130
報告 155 230
閱讀《構建之法》 80 100
博客園編寫 60 100
反思及總結 15 30

通過與實驗二的PSP對比,我覺得我對於我自己過於自信,計划時間始終短於實際完成時間,這就說明我自己的計划有問題,對實驗過於自信。其實討論時花費的時間較長,一方面在討論的時候會出現討論的話題突然轉變,變成無關緊要的話題;另一方面,思考的時候會花費很多時間,比如考慮這樣做好不好,對不對等等一些問題,所以對於PSP的估計中產生的誤差還是需要改變。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM