2015-04-03 17 views
0

我有一個很難追查我的Clojure的實施Bron-Kerbosch algorithm產生一個計算器錯誤。在Clojure的程序跟蹤下來的StackOverflow,包含SSCCE

下面是我的實現算法本身的,這裏是一個SSCCE概述了問題http://pastebin.com/gtpTT4B4的鏈接。

(defn Bron-Kerbosch [r p x graph cliques] 
    ;(println (str "R:" r " P:" p " X:" x " Clq:" cliques)) 
    (cond (and (empty? p) (empty? x)) (concat cliques r) 
     :else 
     (let [neigh (neighV graph (dec (count p)))] 
      (loop [loop-clq '(cliques) 
       loop-cnt (dec (count p)) 
       loop-p '(p) 
       loop-x '(x)] 
      (cond (= -1 loop-cnt) loop-clq 
        :else 
        (recur (concat loop-clq 
           (Bron-Kerbosch (concat r loop-cnt) 
               (concat p neigh) 
               (filter (set x) neigh) 
               graph cliques)) 
         (dec loop-cnt) 
         (filter (set p) loop-cnt) 
         (concat x loop-cnt))))))) 

我會認爲這個問題顯然在於我的兩個引導條件(cond (and (empty? p) (empty? x))一個(cond (= -1 loop-cnt)因爲函數算法是遞歸的範圍內。

雖然這個假設我正確地建立名單x r p。根據評論出的印刷語句的輸出結果來判斷(派系總是打印爲EmptyList)我認爲我的列表理解也可能是問題。

沿着同樣的路線,我可以看到的另一個問題是,我實際上並沒有在BK-Call函數(在SSCCEE)中正確地調用算法。

我的整體問題是,是什麼原因造成的?雖然這太開放了,但可能導致我回答的另一個問題是我如何在第一行中使用print語句。

當打印語句註釋掉它產生的輸出

R:[email protected] P:[email protected] X:[email protected] Clq:[email protected] 

我認爲如果我能看到x r p是在每次調用我也許能看到那裏的算法是怎麼了。

任何人都可以指向正確的方向嗎?

編輯:從SSCCE的neighV功能

(defn neighV [graph nodenum] 
    (let [ret-list (for [i (range (count graph)) :when (contains? (graph i) nodenum)] i)] 
    ret-list)) 

EDIT2: Noisesmith的回答已經得到我更接近解決方案,對我有意義。我將所有concat都包裹在doall中。試圖再次我正在調用該函數後「無法投龍於Seq」的錯誤,我想,這從功能

fptests.core> (BK-Call (sanity1)) 
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505) 
fptests.core> (concat 1 '(2 3)) 
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505) 

所以我當時在'()纏繞。loop-cnt試圖concatloop-cnt到列表朵朵把它變成一個清單之前,它是concat

fptests.core> (concat '(1) '(2 3)) 
(1 2 3) 

其中,我所做的所有這些改變之後,我最終回到我的堆棧溢出。這裏是新的Bron-Kerbosch功能與所有的修改。我想我現在有和我以前一樣的問題了。

儘管新的是,我是否實施了我應該正確的更改,'()的用法是否有意義解決之後出現的問題實施noisesmith的變化?

(defn Bron-Kerbosch1 [r p x graph cliques] 
    (cond (and (empty? p) (empty? x)) (doall (concat cliques r)) 
     :else 
     (let [neigh (neighV graph (dec (count p)))] 
      (loop [loop-clq '(cliques) 
       loop-cnt (dec (count p)) 
       loop-p '(p) 
       loop-x '(x)] 
      (cond (= -1 loop-cnt) loop-clq 
        :else 
        (recur (doall (concat loop-clq 
             (Bron-Kerbosch1 (doall (concat r '(loop-cnt))) 
                 (doall (concat p neigh)) 
                 (filter (set x) neigh) 
                 graph cliques))) 
         (dec loop-cnt) 
         (filter (set p) '(loop-cnt)) 
         (doall (concat x '(loop-cnt))))))))) 

EDIT3:後耐心地等待我prn語句停止(不知道爲什麼,我把他們當我知道這是一個SO)我發現,如果不是所有的語句印刷是沿着線

"R:" (loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt ...) 
"P:" (range (count graph) 0 2 3) " X:"() " Clq:"() 

在檢查了這個之後,我意識到我沒有正確地遞歸調用函數。我一直在聯合項目P而不是刪除它們。這導致P不斷增長。這很可能是我的堆棧溢出的原因。雖然還有一些問題。我仍然在創建一個stackoverflow。

一旦我解決了我的問題繼續工會到P我的問題是,當我concatloop-cnt它不是,我想說,評估爲一個值,但它保持作爲變量名loop-cnt。我懷疑我的堆棧溢出現在處於我的引導條件未滿足的狀態,因爲如果loop-cnt未計算爲數字,則無法滿足此條件。

所以我認爲我的問題現在與concatloop-cnt列表作爲一個數字而不是變量。

+0

發生堆棧溢出時,輸出看起來如何?您可能需要在Clojure中查看更加慣用的BK算法:https://github.com/tgk/bron-kerbosch-in-clojure – mac 2015-04-03 08:35:17

+0

「neighV」函數是什麼樣的? – 2015-04-03 14:13:41

+0

@BobJarvis我在這個問題的編輯中加入了'neighV'。 – KDecker 2015-04-03 14:21:46

回答

0

concat是懶惰的。在concat之上構建concat的遞歸調用,沒有意識到任何先前的懶惰層,每個調用都會增加實現lazy-seq所需的調用堆棧的大小。

這個連接是否需要懶惰?如果不是,請撥打concat以撥打doall。這將使得串聯急切,這減少了實現最終結果所需的調用棧的大小,並因此消除了StackOverflowError。

此外,打印懶惰-SEQ,看到了內容的正確方法是prn,你可以使用pr-str來獲取prprn將在需要時作爲一個字符串使用,值的形式。

+0

謝謝,我會試試這個。我想現在有些混亂。如果我在REPL中評估'(concat'(1)'(2 3))',它會返回'(1 2 3)'。爲什麼我不會收到一些說結果是懶惰的序列而不是評估? //所以不停止的原因是它不能執行任何引導條件,因爲惰性序列不會被消除? – KDecker 2015-04-03 15:13:58

+0

我已經更新了這個問題,我不知何故設法回到我的堆棧溢出。我在你的建議中加入了一個錯誤,並試圖將我的循環計數器(代表一個節點)「concat」到一個列表中。我想我解決了這個問題,並在運行時返回到我的堆棧溢出。 – KDecker 2015-04-03 15:48:09

+0

@KDecker,至少對於nREPL來說,REPL被實現爲默認打印值,如果需要的話可以實現它們的懶惰序列,即使對於無限的懶惰seq。 (有一種方法可以控制它。)要查看某個東西是否是懶惰的seq,請使用'class'。 '(class(concat'(1)'(2 3))'==>'clojure.lang.LazySeq'。 – 2015-04-03 16:05:03

0

我想你是在濫用引用列表。

例如,在(defn Bron-Kerbosch1 [ ... ] ...)'(cliques)計算結果爲含有符號cliques,不含有參數cliques作爲其一種元素的列表的列表。你需要(list cliques)

類似案件比比皆是。

相關問題