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.

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