Hi Josh,
I had a quick look at your code...
If you say that running with reducers cuts runtime to 1/4 the original,
I'll believe you...However, even though our code is very similar, I
don't get any benefit from reducers...Like you, I've got recursion
inside a 'letfn' that uses (r/reduce (rmap ... ...)) and a best-move fn
that uses r/fold on the reducer r/map returns...Unfortunately, despite
having spent 3 days to get r/fold working without complaining - I'm not
seeing any performance benefits whatsoever! it looks like this:
-------------------------------------------------------------------------------------------------------------------------------
(defrecord Tree [root direction children])
(defrecord Move->Tree [move tree])
(defrecord Move->Board [move board])
(defrecord Move-Value [move value])
(defn best
([] Integer/MIN_VALUE)
([best next]
(if (pos? (compare (:value best) (:value next)))
best next)))
(defn next-level "Returns all the possible next-boards as the result of
trying out all the moves of this team"
[b dir]
(r/map #(Move->Board. % (core/try-move %))
(core/team-moves @curr-game b dir)))
(defn my-max
([x y] (max x y))
([] Integer/MIN_VALUE))
(defn my-min
([x y] (min y x))
([] Integer/MAX_VALUE))
(defn game-tree "Generate the game tree."
[dir board successors-fn]
(Tree. board dir
(r/map #(Move->Tree. (:move %)
(game-tree (- dir) (:board %) successors-fn))
(successors-fn board dir))))
(defn search "The recursion of min-max algorithm."
[eval-fn tree depth]
(letfn [(minimize [tree d] (if (zero? d) (eval-fn (:root tree)
(:direction tree))
(r/reduce my-min
(r/map #(maximize (:tree %) (dec d))
(:children tree)))))
(maximize [tree d] (if(zero? d) (eval-fn (:root tree)
(:direction tree))
(r/reduce my-max
(r/map #(minimize (:tree %) (dec d))
(:children tree)))))]
(minimize tree depth)))
(defn best-move "Start folding here." [dir b d]
(r/fold best
(r/map #(Move-Value. (:move %) (search score-by-count (:tree %) d))
(:children (game-tree dir b next-level)))))
-----------------------------------------------------------------------------------------------------------------------------------------
I really really don't understand why nothing happens in parallel even
though I'm carefully using r/fold at the top and r/reduce, r/map in
between!
Your code confirms that my rationale is not wrong - at least not
completely...I should be seeing massive performance benefits! Havinf
done somehtign similar yourself if you can provide any insight that
would be fantastic!
Jim
On 22/08/12 00:12, Joshua Ballanco wrote:
Not sure if you'd consider this "real code", but I recently wrote a
scrabble solver (i.e. find the best scoring word given a set of letters)
in such a way that it can be used with or without reducers:
https://github.com/jballanc/scrabbler
Running with reducers cuts runtime to 1/4 the original.
- Josh
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en