PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/test/fuzzy_cmeans/test/core.clj

http://github.com/jfinken/fuzzy-cmeans
Clojure | 144 lines | 113 code | 13 blank | 18 comment | 15 complexity | 55c09cccec36a560a763681e491f4412 MD5 | raw file
  1. (ns fuzzy-cmeans.test.core
  2. (:require [fuzzy-cmeans.core :as fuzzy] :reload)
  3. (:use [clojure.contrib.string :only (blank?)])
  4. (:use [incanter core stats charts])
  5. (:use [clojure.test]))
  6. ;(deftest replace-me ;; FIXME: write
  7. ; (is false "No tests have been written."))
  8. ;------------------------------------------------------------------------------
  9. ; code to read a CSV of data points - currently unused
  10. ;------------------------------------------------------------------------------
  11. (defn read-points-file
  12. [path]
  13. (with-open [rdr (clojure.java.io/reader path)]
  14. (reduce conj [] (line-seq rdr))))
  15. (defn parse-point-str
  16. "Given a comma-separated point as a string, return
  17. a vector of doubles"
  18. [pt-str]
  19. (let [temp (.split pt-str ",")]
  20. (loop [side nil
  21. ret-vec (vector)
  22. more (seq temp)]
  23. (if (not (blank? (first more)))
  24. (recur
  25. (println "first more:" (first more))
  26. (conj ret-vec (Double/parseDouble (first more)))
  27. (next more))
  28. ret-vec))))
  29. (defn parse-points-file
  30. "Given a file where each line is a comma-sep list of dimensional
  31. values, construct a ClusterPoint for each"
  32. [path]
  33. (let [raw-pts-vec (read-points-file path)]
  34. (loop [ret-pts (vector)
  35. more (seq raw-pts-vec)]
  36. (if (boolean (seq (first more)))
  37. (recur (conj ret-pts (fuzzy/make-cluster-point (parse-point-str (first more)) -1))
  38. (next more))
  39. ret-pts))))
  40. ;------------------------------------------------------------------------------
  41. ; Client code
  42. ;------------------------------------------------------------------------------
  43. ; Generate random points
  44. (defn gen-cluster-points
  45. "Return a vector of n cluster points with random coordinate values
  46. within the given range"
  47. [n xmin xmax ymin ymax]
  48. (loop [m n ret (vector)]
  49. (if (zero? m)
  50. ret
  51. (recur
  52. (dec m)
  53. (conj ret
  54. (fuzzy/make-cluster-point
  55. (vector
  56. ( + (mod (rand Integer/MAX_VALUE) (inc (- xmax xmin))) xmin) ;x
  57. ( + (mod (rand Integer/MAX_VALUE) (inc (- ymax ymin))) ymin));y
  58. -1))))))
  59. (defn main
  60. []
  61. (let [in-fuzzy 2.0
  62. eps (Math/pow 10 -8)
  63. xmin 1 xmax 500
  64. ymin 1 ymax 500
  65. num-clusters 5
  66. num-points 3000]
  67. (let [data-pts (gen-cluster-points num-points xmin xmax ymin ymax)
  68. centroids (gen-cluster-points num-clusters xmin xmax ymin ymax)]
  69. ; init fuzzy-cmeans
  70. (fuzzy/init-cmeans data-pts centroids in-fuzzy eps)
  71. ; print clusters just for fun..
  72. (fuzzy/print-clusters)
  73. ; run
  74. (fuzzy/run)
  75. )))
  76. ;------------------------------------------------------------------------------
  77. ; Visualize with Incanter
  78. ;------------------------------------------------------------------------------
  79. (defn third
  80. [more]
  81. (first (next (next more))))
  82. (defn dump-points-for-incanter
  83. []
  84. (loop [i 0 ret (list)]
  85. (if (> i (- (count (fuzzy/get-data-points)) 1))
  86. ret
  87. (recur
  88. (inc i)
  89. (cons (conj (:coords ((fuzzy/get-data-points) i))
  90. (:cluster-index ((fuzzy/get-data-points) i)))
  91. ret)))))
  92. (defn dump-clusters-for-incanter
  93. []
  94. (loop [i 0 ret (list)]
  95. (if (> i (- (count (fuzzy/get-cluster-centroids)) 1))
  96. ret
  97. (recur
  98. (inc i)
  99. (cons (conj (:coords ((fuzzy/get-cluster-centroids) i))
  100. (:cluster-index ((fuzzy/get-cluster-centroids) i)))
  101. ret)))))
  102. (comment
  103. (defn dump-point-cluster-indices
  104. []
  105. (loop [i 0 ret (vector)]
  106. (if (> i (- (count @data-points) 1))
  107. ret
  108. (recur
  109. (inc i)
  110. (conj ret (:cluster-index (@data-points i)))))))
  111. )
  112. (defn get-scatter-title
  113. [data]
  114. (str "fuzzy c-means (" (count data) " data points)"))
  115. ; grab the data and visualize with a scatter-plot
  116. (defn incanter-vis
  117. []
  118. (let [data (dump-points-for-incanter)
  119. center-data (dump-clusters-for-incanter)]
  120. (let[ X (map first data)
  121. Y (map second data)
  122. cs (map third data)
  123. center_xs (map first center-data)
  124. center_ys (map second center-data)]
  125. (let [ plot (doto (scatter-plot X Y :group-by cs :title (get-scatter-title data))
  126. (add-points center_xs center_ys))]
  127. (view plot)))))
  128. ; generate points and run fuzzy cmeans
  129. (main)
  130. ; visualize
  131. (incanter-vis)