本發明涉及一種基于圖挖掘的軟件函數變更預測系統及方法,屬于復雜網絡和數據分析及軟件工程領域。
背景技術:
復雜網絡經常伴隨著信息、病毒、疾病等的傳播,而一個網絡的拓撲結構對于變更傳播的程度有著顯著的影響。在計算機科學領域,大型軟件系統中的類圖、依賴圖、關系圖、軟件組件圖、函數調用圖都屬于復雜網絡。
當開發者為了加入一個新功能或者修復一個BUG的時,對軟件系統一個部分作出修改后,其他的部分為了適應修改,常常也需要進行更新。量化一個軟件網絡的傳播性有助于節省軟件維護產生的開銷。
在函數調用關系圖中,變更傳播通常都是單方向的,函數A調用函數B,當B發生修改時,A因為接口需要作出調整因此很可能需要相應作出修改,這叫B傳播到A,但當A發生修改時,B一般就不需要作出修改了。
數據挖掘就是從大量的、不完全的、有噪聲的、模糊的、隨機的數據中,提取隱含在其中的、人們事先不知道的、但又是潛在有用的信息和知識的過程。這些數據可以是結構化的,如關系數據庫中的數據,也可以是半結構化的,如文本、圖形、圖像數據,甚至是分布在網絡上的異構型數據。針對半結構化數據的研究已經成為近年來國內外數據挖掘領域的研究熱點,而目前國內的研究熱點主要集中在文本數據挖掘等領域,針對圖的數據挖掘研究才剛剛開始。與一般的數據比較,圖能夠表達更加豐富的語義,在科學研究和許多商業領域有著更為廣泛的應用。同時,這種豐富的語義也增加了數據結構的復雜性和挖掘令人感興趣的圖的子結構的難度。因此,需要綜合應用圖論知識與數據挖掘的各種技術。圖的數據挖掘主要是從圖的數據庫中找到大于最小支持度的頻繁子圖。
基于貪心策略的頻繁子圖挖掘是頻繁子圖挖掘領域最先發展起來的技術之一,其中最著名的是SUBDUE算法。SUBDUE算法基于最小描述長度原則(minimum description length,MDL)來發現子結構。嚴格來說,其所謂的頻繁與之后我們介紹的頻繁子圖的概念有所不同。其所指的某個子結構“頻繁”是用MDL原則評定的,而不是單純指其出現的頻率高。
對于許多挖掘和學習問題來說,描述關系通常比描述屬性更能得出簡潔且精確的規則。與之相對應的,一階謂詞邏輯在很多情況下的表現也優于命題邏輯。而且,圖可以比較容易的使用一階邏輯來表示。對基于ILP的方法而言,其優點不局限于發現知識,還可以在知識歸納中運用正反例。或者說,其目標是歸納出一個可正確分類的正樣本集和負樣本集的規則集。是故,歸納邏輯編程(Inductive Logic Programming,ILP)被提出而應用在頻繁子圖的搜索上。其優點在于大多算法能找出出現頻率高的子圖,且能作為交好的類識別器。但其缺點在于不能保證發現所有的頻繁子圖。1998年Dehaspe基于ILP提出可對頻繁子圖進行完全挖掘的WARMR算法,其算法核心思想與Apriori算法類似。
比較遺憾的是,基于ILP的算法由于需要圖結構對一些特別的特征和謂詞實例進行預特征化,故僅能發現有限特征的子結構,無法發現所有的頻繁子圖。而且雖然其在后續發展中結合了分層搜索以最小化對數據庫的訪問,效率有了極大的提升,但是,其搜索所需空間仍就很大。由此A.Inokuchi等人最先提出了基于Apriori思想的頻繁子結構挖掘算法。(AGM算法)
FSG是AGM算法的一種改進。同基于Apriori的方法一樣,其采用了分級擴展的方法。但優化之處在于:其采用了相對稀疏的圖表示方法,來最小化存儲空間和計算開銷。每次添加一條邊來擴大頻繁子圖的大小,由此使得生成候選集更有效。采用了對小圖更有效的規范標簽和圖同構算法。其對生成候選集進行了各種優化并統計了能適用于大規模的圖數據庫的優化措施。
AGM和FSG算法都采用了基于Apriori逐層推進的方法。而這種Apriori模式的算法會遇到兩個瓶頸:從k階頻繁子圖構造k+1階頻繁子圖相當復雜且代價昂貴,同時子圖同構測試是一個NPC問題,所以處理誤報的代價也是極其昂貴。為了解決這些問題,Xifeng Yan提出了gSpan(graph-based Substructure pattern mining)算法,通過對圖進行深度優先搜索遍歷來發現頻繁子圖。gSpan算法由于解決了模式的算法所遇到的兩個瓶頸,大幅提高了效率并降低了空間消耗,同時避免發生產生冗余候選頻繁子圖的情況。
在圖數據集中進行模式挖掘的過程中,實際上會遇到諸多相當棘手的問題,諸如子圖同構檢測。這些問題在圖數據中通常意味著遠超于其他數據結構的昂貴的時間代價。由此,一種新的頻繁子圖挖掘算法算法快速頻繁子圖挖掘(Fast Frequent Subgraph Mining,FFSM)被提出。FFSM采用了垂直搜索模式,最終能減少產生的冗余候選子圖。
頻繁子圖挖掘技術在發展過程中,由基于貪心策略的SUBDUE算法到基于ILP的方法,再到A.Inokuchi等人提出了基于Apriori思想的AGM算法,頻繁子圖的效率逐步提升。FSG算法對AGM算法作出了圖的表示形式以及生成候選頻繁子圖過程的優化,提升了效率并降低了開銷,但是其效果并不十分明顯。直到基于模式增長的方法——gSpan算法被提出,開創性的結合了DFS搜索,并定義了DFS序列來減少冗余頻繁子圖的生成,大幅提高了效率并降低了空間消耗。而FFSM算法為了解決基于Apriori思想的算法會面臨的兩個挑戰做出了相應的對策,通過解決潛在的子圖同構問題并減少冗余候選子圖的生成,也大大提升了效率。
綜上,現有的圖挖掘技術存在如睛問題:(1)現有圖挖掘技術主要還是集中在物理、化學、網絡領域。沒有涉及到函數變更預測上。(2)現有的圖挖掘技術由于要找出所有頻繁子圖,所以時間開銷特別大。(3)由于圖挖掘技術找出所有頻繁子圖,所以數據量特別大,對于后續處理也帶來很大麻煩。
技術實現要素:
本發明的技術解決問題:克服現有技術的不足,提供一種基于圖挖掘的軟件函數變更預測系統及方法,具有時間開銷低、數據量小的特點,并且挖掘效果很好,挖掘出的預測函數在下個版本發生變更的數目與總數的比值大于80%。
本發明技術解決方案:
一種基于圖挖掘的軟件函數變更預測系統,包括函數調用關系圖生成模塊、變更函數調用關系圖獲取模塊、圖挖掘及變更函數預測模塊,其中:
函數調用關系圖生成模塊:根據需要處理相應的軟件網絡,生成相應軟件網絡的函數調用關系圖;
變更函數調用關系圖獲取模塊:對相鄰版本的函數源碼比較,得到變更函數,在已生成的函數調用關系圖中,去掉沒有變更的函數,得到每個相鄰版本源代碼的變更函數調用關系圖;
圖挖掘及變更函數預測模塊:利用得到的變更函數調用關系圖,通過圖挖掘算法,輸入參數,再得到挖掘結果,并輸出預測函數。
所述函數調用關系圖生成模塊實現過程如下:
(1)選擇需要處理相應的軟件網絡,包括操作系統軟件源代碼,然后調用外部工具cdepn,對于所有.c文件,生成相應的cdepn文件;
(2)對于生成的.cdepn文件,逐行讀取文件,當每一行第一個字符為F時,表示該行函數為call函數,之后的所有開頭第一個字符為C的行的直到文件尾或者下一個開頭第一個字符為F的行為止,包含在里面的函數都被該函數調用,按照此方法則生成相應整個軟件網絡的函數調用關系圖。
所述變更函數調用關系圖獲取模塊實現過程如下:
(1)利用ctags獲取每個函數在相鄰版本中的被定義位置,函數定義總是以‘{’開始,最終以‘}’結束,利用此原理,從函數開始行開始,利用棧的數據結構,去掉注釋語句,每讀到‘{’入棧,讀到‘}’出棧,直到棧為空,這時候的行數為該函數的結束行。按照此方法得到函數被定義的結束行,然后提取各函數在相鄰版本的源代碼,利用diff命令,比較代碼是否發生改變,如果是則是變更函數;
(2)得到變更函數后,利用變更函數,對源代碼的函數調用關系圖進行篩選,去掉沒有變更過的函數,剩下的就是變更函數調用關系圖。
所述圖挖掘及變更函數預測模塊實現過程如下:
(1)設定參數,包括最小支持度,以及單次挖掘的相鄰版本子圖數,即跨度,利用修改過的gspan算法進行挖掘,如下:
1)首先逐條邊讀取一定數量的連續版本變更函數子圖,對于每條邊,記錄出現次數,讀取完畢后,去掉出現次數低于支持度的邊;
2)剩余邊具有以下屬性:(x,x1,y,y1,e),x為調用函數的編號,x1是該函數的權值,y是被調用函數的編號,y1是該函數權值,e是該條邊的編號,以上五個屬性都是數字,按照從左到右優先級順序對所有邊按照屬性值比較從低到高進行排序,得到最小DFS編碼,從記錄的第一個函數開始,按照最小DFS編碼的邊的順序,從小到大進行擴展,不斷加入新的邊,直到得到完整的頻繁變更子圖;
(2)利用挖掘出的頻繁變更子圖,得到頻繁變更函數即挖掘結果,并作為輸出的預測函數。
一種基于圖挖掘的軟件函數變更預測方法,實現步驟如下:
第一步,生成函數調用關系圖,根據需要處理相應的軟件網絡,生成相應軟件網絡的函數調用關系圖;
第二步,獲取變更函數,根據已生成的函數調用關系圖,去掉圖中所有沒有發生變更的函數,得到每個相鄰版本源代碼的變更函數調用關系圖;
第三步,圖挖掘及變更函數預測,利用得到的變更函數調用關系圖,通過圖挖掘算法,輸入參數,得到挖掘結果,并輸出預測函數。
所述第一步,具體如下:
在Linux下配置工具生成cdepn圖,并通過腳本處理進而生成callpah,具體如下:(1)配置Codeviz工具;(2)編寫腳本遍歷目錄為所有.c文件生成cdepn文件;(3)編寫代碼,利用cdepn文件生成該軟件網絡的函數調用關系圖。
所述第二步,具體過程如下:
步驟2.1、利用ctags可以對某個.c文件下所有的函數進行檢索,并輸出該函數的起始行,編寫腳本,遞歸遍歷Linux內核代碼下所有.c文件生成相應的.c文件;
步驟2.2、函數定義總是以‘{’開始,最終以‘}’結束,利用此原理,從函數開始行開始,利用棧的數據結構,去掉注釋語句,每讀到‘{’入棧,讀到‘}’出棧,直到棧為空,這時候的行數為該函數的結束行;
步驟2.3、得到起始行后,利用shell命令,sed可以讀取指定行之間的內容,通過diff命令,比較相鄰版本間同名函數,可以知道該函數是被修改、被增加或者被刪除;
步驟2.4、在得到相鄰版本間的變更函數后,在之前生成的函數調用關系圖中,去掉沒有發生變更的函數,得到相鄰版本變更函數調用關系圖。
所述第三步,具體過程如下:
步驟3.1、設定參數,包括最小支持度及單次挖掘的相鄰版本子圖數,即跨度,所述跨度是單次挖掘的相鄰版本子圖數,本發明主要采用了跨度為3、5、7、10四個值作為參數,每次選取N個相鄰版本子圖作為挖掘數據源;所述最小支持度是指設定最小支持度a,表示選取N個版本時,挖掘出的子圖在這N個版本中出現次數S比上N,S/N>=a,本發明采用支持度0.4、0.6、0.8、1作為候選參數;
步驟3.2、利用編寫的gspan算法代碼,進行挖掘,得到頻繁子圖,其中支持度大于設定值的函數即為下個版本的預測結果。
本發明的優點與積極效果在于:本發明利用圖挖掘進行變更函數預測屬于領域內創新,并且挖掘效果很好。
本發明與現有技術相比的優點在于:
(1)本發明首次將圖挖掘技術用在函數變更預測領域,屬于領域創新,具有時間開銷低、數據量小的特點,并且挖掘效果很好,挖掘出的預測函數在下個版本發生變更的數目與總數的比值大于80%。
(2)本發明采用gspan算法,并根據軟件網絡沒有同名結點的特點,對gspan算法進行優化,統計的是最大頻繁變更子圖,原gspan算法不僅統計最大頻繁變更子圖,也統計了子圖的子圖,因此時間復雜度從2^n降低到了n^2。
(3)本發明優化了gspan算法,挖掘結果只會輸出最大頻繁變更子圖,而不是現有的算法將最大頻繁變更子圖所有子集輸出,對于后續處理更加容易。
附圖說明
圖1為本發明系統的結構框圖;
圖2為圖1中函數調用關系圖生成模塊的實現流程圖;
圖3為圖1中變更函數調用關系圖獲取模塊的實現流程圖;
圖4為圖1中圖挖掘及變更函數預測模塊的實現流程圖;
圖5為cdepn文件格式。
具體實施方式
下面將結合附圖和實施例對本發明作進一步的詳細說明。
在敘述之前,要對本發明涉及的技術和術語進行一下說明。
Codeviz,graphviz,ctags,sed是Linux下的第三方工具,在命令行輸入sudo apt-get install工具名命令可以直接安裝。
cdepn文件是利用安裝好的codeviz和graphviz后,針對待處理源代碼文件下的.c文件生成的相應的名字為*.cdepn文件,文件格式如圖5所示。
Shell命令是Linux自帶的命令行編輯器,用于處理各種常用操作。
如圖1所示,本發明包括函數調用關系圖生成模塊、變更函數調用關系圖獲取模塊和圖挖掘及變更函數預測模塊。
如圖2所示,本發明中函數調用關系圖生成模塊具體實現如下:
(1)掃描源代碼下未處理過的源代碼文件,生成對應的cdepn文件;
(2)所有源代碼處理完畢后,逐行讀取所有cdepn文件,逐行讀取文件,當讀到開頭為F時,表示該行函數為call函數,之后的所有開頭為C的行的直到文件尾或者下一個F開頭行為止,包含在里面的函數都被該函數調用,按照此方法生成整個軟件網絡的調用關系圖。
如圖3所示,本發明中變更函數調用關系圖獲取模塊具體實現如下:
(1)利用Linux工具ctags,輸入源代碼下的源文件,得到該文件下所有函數被定義的起始行以及所在文件路徑。
(2)函數定義總是以‘{’開始,最終以‘}’結束,利用此原理,從函數開始行開始,利用棧的數據結構,去掉注釋語句,每讀到‘{’入棧,讀到‘}’出棧,直到棧為空,這時候的行數為該函數的結束行。
(3)使用Linux的diff命令,比較相鄰版本函數源代碼是否發生變更。
(4)去掉函數調用關系圖中沒有發生變更的函數,剩下的圖就是變更函數調用關系圖。并作為結果輸出。
如圖4所示,本發明中圖挖掘及變更函數預測模塊具體實現如下:
(1)設定挖掘參數,最小支持度和跨度。
最小支持度:設定最小支持度a,表示選取N個版本時,挖掘出的子圖在這N個版本中出現次數S比上N,S/N>=a。本發明采用支持度0.4、0.6、0.8、1作為候選參數。
跨度:單次挖掘的相鄰版本子圖數,本發明主要采用了跨度為3、5、7、10四個值作為參數,每次選取N個相鄰版本子圖作為挖掘數據源。
(2)利用gspan算法進行挖掘,輸出結果是挖掘出的頻繁變更子圖。
(3)提取挖掘出的頻繁變更子圖中的所有函數,作為結果輸出。
本發明方法,具體為如下步驟。
第一步、獲得函數調用圖:
在Linux下配置工具生成cdepn圖,并通過腳本處理進而生成callpah。基本的思路如下:(1)配置Codeviz等工具;(2)編寫腳本遍歷目錄為所有.c文件生成cdepn文件;(3)編寫代碼,利用cdepn文件生成該網絡的函數調用關系圖。
步驟1.1、配置工具。
首先安裝graphviz和CodeViz
使用配置好的工具遞歸編譯待處理源代碼下所有*.c文件,會相應地生成一個*.c.cdepn文件。
步驟1.2、執行腳本生成函數調用關系圖。
利用編寫的代碼生成函數調用關系圖,對于生成的.cdepn文件,逐行讀取文件,當讀到開頭為F時,表示該行函數為call函數,之后的所有開頭為C的行的直到文件尾或者下一個F開頭行為止,包含在里面的函數都被該函數調用,按照此方法生成整個軟件網絡的調用關系圖。
第二步、通過相鄰版本函數調用圖獲得變更函數,包括:
步驟2.1、部署ctags,利用ctags得到每個函數在源代碼中定義的起始行;
利用sudo apt-get install ctags安裝ctags;
ctags可以對某個.c文件下所有的函數進行檢索,并輸出該函數被定義的起始行。編寫腳本,遞歸遍歷Linux內核代碼下所有.c文件生成相應的.c文件。
步驟2.2、利用模式匹配,得到每個函數的結束行;
函數定義總是以‘{’開始,最終以‘}’結束,利用此原理,從函數開始行開始,利用棧的數據結構,去掉注釋語句,每讀到‘{’入棧,讀到‘}’出棧,知道棧為空,這時候的行數為該函數的結束行。
步驟2.3、利用相鄰版本函數的起始行,結束行,提取出源代碼,進行比較,得到修改、增加、刪除的函數。
得到起始行后,利用shell命令,sed可以讀取指定行之間的內容,通過diff命令,比較相鄰版本間同名函數,可以知道該函數是被修改、被增加或者被刪除。
步驟2.4、得到發生修改函數的子圖,及變更函數子圖;
通過變更函數集合,在原內核生成的call graph上進行篩選,得到的子圖即為變更函數的子圖。
第三步、利用圖挖掘算法gspan,設定參數,得到頻繁子圖,輸出結果;
步驟3.1、設定參數,主要有最小支持度,還有單次挖掘的相鄰版本子圖數,即跨度。
跨度,單次挖掘的相鄰版本子圖數,本發明主要采用了跨度為3、5、7、10四個值作為參數,每次選取N個相鄰版本子圖作為挖掘數據源。
最小支持度,設定最小支持度a,表示選取N個版本時,挖掘出的子圖在這N個版本中出現次數S比上N,S/N>=a。本發明采用支持度0.4、0.6、0.8、1作為候選參數。
步驟3.2、利用編寫的代碼,進行挖掘,得到頻繁子圖。其中支持度大于設定值的函數即為下個版本的預測結果。
提供以上實施例僅僅是為了描述本發明的目的,而并非要限制本發明的范圍。本發明的范圍由所附權利要求限定。不脫離本發明的精神和原理而做出的各種等同替換和修改,均應涵蓋在本發明的范圍之內。