You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

323 lines
7.6 KiB

  1. package util
  2. import model.Coord
  3. import scala.math._
  4. import scala.collection.mutable.ArrayBuffer
  5. import scala.collection.mutable
  6. import model.Customer
  7. import scala.io.BufferedSource
  8. import scala.reflect.ClassTag
  9. object Util {
  10. private val r = 6471.00 // km
  11. def toRad(num: Double): Double = {
  12. val a = num * Pi / 180
  13. a
  14. }
  15. def getHaversineDistance(c1: Coord, c2: Coord): Double = {
  16. val x1 = c1.latitude - c2.latitude
  17. val x2 = c1.longitude - c2.longitude
  18. val dlat = toRad(x1)
  19. val dlon = toRad(x2)
  20. val a = pow(sin(dlat / 2), 2) +
  21. cos(toRad(c1.latitude)) *
  22. cos(toRad((c2.latitude))) *
  23. pow(sin(dlon / 2), 2)
  24. val c = 2 * atan2(sqrt(a), sqrt(1 - a))
  25. val d = r * c
  26. d
  27. }
  28. def getHaversineDistance(lat: Double, lon: Double): Double = {
  29. val x1 = lat
  30. val x2 = lon
  31. val dlat = toRad(x1)
  32. val dlon = toRad(x2)
  33. val a = pow(sin(dlat / 2), 2) +
  34. cos(toRad(x1)) *
  35. cos(toRad((0))) *
  36. pow(sin(dlon / 2), 2)
  37. val c = 2 * atan2(sqrt(a), sqrt(1 - a))
  38. val d = r * c
  39. d
  40. }
  41. def primTraverse(
  42. arr1: Array[Array[Int]],
  43. comp: Int,
  44. cond: (Int, Int) => Boolean,
  45. cb: (Int, Int, Array[Array[Int]], Array[Array[Int]]) => Array[Array[Int]]
  46. ): Unit = {
  47. val n = arr1.length
  48. val selected = Array.ofDim[Boolean](n)
  49. val arr2: Array[Array[Int]] = Array.ofDim(n, n)
  50. selected(0) = true
  51. // val mst: Array[Array[Int]] = Array.ofDim(5, 5)
  52. for (_ <- 0 until n - 1) {
  53. // var min = 999999
  54. var x = 0
  55. var y = 0
  56. for (i <- 0 until n) {
  57. if (selected(i) == true) {
  58. for (j <- 0 until n) {
  59. if (selected(j) == false && arr1(i)(j) != 0) {
  60. if (cond(comp, arr1(i)(j))) {
  61. x = i
  62. y = j
  63. cb(x, y, arr1, arr2)
  64. }
  65. }
  66. }
  67. }
  68. }
  69. // mst(x)(y) = mst(x)(y)
  70. selected(y) = true
  71. }
  72. }
  73. def mstUsingPrims[T: ClassTag](
  74. edges: Array[Array[T]]
  75. )(implicit num: Numeric[T]): Array[Array[T]] = {
  76. val n = edges.length
  77. val selected: ArrayBuffer[Boolean] = ArrayBuffer.fill(n)(false)
  78. selected(0) = true
  79. val mst: Array[Array[T]] = Array.ofDim[T](n, n)
  80. for (_ <- 0 until n - 1) {
  81. var min = 999999
  82. var x = 0
  83. var y = 0
  84. for (i <- 0 until n) {
  85. if (selected(i) == true) {
  86. for (j <- 0 until n) {
  87. if (selected(j) == false && edges(i)(j) != 0) {
  88. if (num.gt(num.fromInt(min), edges(i)(j))) {
  89. min = num.toInt(edges(i)(j))
  90. x = i
  91. y = j
  92. }
  93. }
  94. }
  95. }
  96. }
  97. // println(s"Edge selected $x - $y : ${edges(x)(y)}")
  98. mst(x)(y) = edges(x)(y)
  99. mst(y)(x) = edges(x)(y)
  100. selected(y) = true
  101. }
  102. mst
  103. }
  104. def findClusters[T](
  105. mst: Array[Array[T]],
  106. centroids: IndexedSeq[Int],
  107. removed: IndexedSeq[(Int, Int, T)]
  108. )(implicit num: Numeric[T]) =
  109. (
  110. centroids,
  111. centroids
  112. .map(d => {
  113. val y = DFS(d, mst)
  114. y(0) -> y
  115. })
  116. .toMap,
  117. removed
  118. )
  119. def makeAdjacencyList(
  120. mst: Array[Array[Int]],
  121. centroids: IndexedSeq[Int]
  122. ): ArrayBuffer[ArrayBuffer[Int]] = {
  123. val n = mst.length
  124. // val selected: ArrayBuffer[Boolean] = ArrayBuffer.fill(n)(false)
  125. val buf: ArrayBuffer[ArrayBuffer[Int]] =
  126. ArrayBuffer.fill(n)(ArrayBuffer.empty)
  127. // for (_ <- 0 until n -1) {
  128. // }
  129. for (i <- 0 until n) {
  130. for (j <- 0 until n) {
  131. if (mst(i)(j) != 0) {
  132. // println(s" $i $j = ${mst(i)(j)}")
  133. buf(i) += j
  134. }
  135. }
  136. }
  137. buf
  138. }
  139. def findCentroids[T](
  140. mst: Array[Array[T]]
  141. )(
  142. implicit ev: Numeric[T]
  143. ): (Array[Array[T]], IndexedSeq[Int], IndexedSeq[(Int, Int, T)]) = {
  144. val n = mst.length
  145. val centroids: mutable.Set[Int] = mutable.Set.empty
  146. val removed: ArrayBuffer[(Int, Int, T)] = ArrayBuffer.empty
  147. for (i <- 0 until n) {
  148. for (j <- 0 until n) {
  149. if (ev.gt(mst(i)(j), ev.fromInt(20)) && mst(i)(j) != 0) {
  150. // println(s" $i $j = ${mst(i)(j)}")
  151. centroids += i
  152. centroids += j
  153. removed.append((i, j, mst(i)(j)))
  154. mst(i)(j) = ev.zero
  155. }
  156. }
  157. }
  158. (mst, centroids.toIndexedSeq, removed.toIndexedSeq)
  159. }
  160. def DFS[T](
  161. start: Int,
  162. graph: Array[Array[T]]
  163. )(implicit num: Numeric[T]): ArrayBuffer[Int] = {
  164. val visited = Array.fill(graph.size)(false)
  165. val buf = ArrayBuffer[Int]()
  166. def loop(
  167. start: Int,
  168. graph: Array[Array[T]],
  169. visited: Array[Boolean]
  170. ): Unit = {
  171. visited(start) = true
  172. buf += start
  173. // print(s"$start ")
  174. for (i <- 0 until graph.size) {
  175. if (num.gt(graph(start)(i), num.fromInt(0)) && (!visited(i))) {
  176. loop(i, graph, visited);
  177. }
  178. }
  179. }
  180. loop(start, graph, visited)
  181. // println()
  182. buf
  183. }
  184. def DFS(
  185. start: Int,
  186. graph: Array[Array[Int]],
  187. num: Int,
  188. cond: (Int, Int) => Boolean
  189. ): ArrayBuffer[Int] = {
  190. val visited = Array.fill(graph.size)(false)
  191. val buf = ArrayBuffer[Int]()
  192. def loop(
  193. start: Int,
  194. graph: Array[Array[Int]],
  195. visited: Array[Boolean]
  196. ): Unit = {
  197. visited(start) = true
  198. buf += start
  199. // print(s"$start ")
  200. for (i <- 0 until graph.size) {
  201. if (graph(start)(i) > 0 && cond(graph(start)(i), num) && (!visited(i))) {
  202. loop(i, graph, visited);
  203. }
  204. }
  205. }
  206. loop(start, graph, visited)
  207. // println()
  208. buf
  209. }
  210. def groupClusters[T](
  211. centroids: IndexedSeq[Int],
  212. clusters: Map[Int, ArrayBuffer[Int]],
  213. removed: IndexedSeq[(Int, Int, T)]
  214. )(implicit num: Numeric[T]) =
  215. centroids
  216. .map(c => {
  217. val cluster = clusters(c)
  218. val lst = removed
  219. .filter(r => {
  220. c == r._1
  221. })
  222. .sortWith((x, y) => {
  223. num.lt(x._3, y._3)
  224. })
  225. .map(l => {
  226. (l._2, l._3)
  227. })
  228. c -> lst
  229. })
  230. .toMap
  231. def getCustomers(
  232. infile: BufferedSource
  233. ): String Either IndexedSeq[Customer] = {
  234. var customers: String Either IndexedSeq[Customer] = Right(IndexedSeq.empty)
  235. val it = infile.getLines
  236. @annotation.tailrec
  237. def loop(
  238. lst: IndexedSeq[Customer],
  239. iter: Iterator[String]
  240. ): String Either IndexedSeq[Customer] = {
  241. if (!iter.hasNext)
  242. return Right(lst)
  243. val line = iter.next
  244. val arr = line.split(",").map(_.trim)
  245. arr match {
  246. case Array(latitude, longitude, workLoad) => {
  247. val cust =
  248. Customer(
  249. Coord(latitude.toDouble, longitude.toDouble),
  250. workLoad.toFloat
  251. )
  252. loop(lst :+ cust, iter)
  253. }
  254. case _ =>
  255. Left(
  256. "Error reading customers from" +
  257. s" file - ${arr.mkString(", ")}"
  258. )
  259. }
  260. }
  261. try {
  262. customers = loop(IndexedSeq.empty, it)
  263. } catch {
  264. case e: NumberFormatException =>
  265. customers = Left(
  266. s"Expected number but received string ${e.getMessage()}"
  267. )
  268. case e: NullPointerException =>
  269. customers = Left("Input was null")
  270. }
  271. customers
  272. }
  273. def formAdjMatrix(customers: IndexedSeq[Customer]): Array[Array[Double]] = {
  274. val n = customers.length
  275. val edges: Array[Array[Double]] = Array.ofDim(n, n)
  276. for (i <- 0 until n) {
  277. for (j <- i until n) {
  278. val weight =
  279. getHaversineDistance(customers(i).location, customers(j).location)
  280. edges(i)(j) = weight
  281. edges(j)(i) = weight
  282. }
  283. }
  284. edges
  285. }
  286. }