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.

325 lines
7.7 KiB

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