temp commit
This commit is contained in:
parent
ab02a1e495
commit
7d045e79b6
@ -24,23 +24,15 @@ class HHCSim(
|
|||||||
)
|
)
|
||||||
.tap(logCentroids)
|
.tap(logCentroids)
|
||||||
.tap(logRemovedEdges)
|
.tap(logRemovedEdges)
|
||||||
.map(
|
.map {
|
||||||
e =>
|
case (mst, centroids, removed) =>
|
||||||
e match {
|
Util.findClusters(mst, centroids, removed)
|
||||||
case (mst, centroids, removed) => {
|
}
|
||||||
printGraph(mst)
|
|
||||||
Util.findClusters(mst, centroids, removed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.tap(logClusters)
|
.tap(logClusters)
|
||||||
.map(
|
.map {
|
||||||
e =>
|
case (centroids, clusters, removed) =>
|
||||||
e match {
|
Util.groupClusters(centroids, clusters, removed)
|
||||||
case (centroids, clusters, removed) =>
|
}
|
||||||
Util.groupClusters(centroids, clusters, removed)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
def checkEmpty(
|
def checkEmpty(
|
||||||
customers: IndexedSeq[Customer]
|
customers: IndexedSeq[Customer]
|
||||||
|
@ -6,6 +6,7 @@ import util.Util
|
|||||||
import config.Conf
|
import config.Conf
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import scala.io.Source
|
import scala.io.Source
|
||||||
|
import sim.HHCSim2
|
||||||
object Main {
|
object Main {
|
||||||
def main(args: Array[String]): Unit = {
|
def main(args: Array[String]): Unit = {
|
||||||
|
|
||||||
@ -13,25 +14,32 @@ object Main {
|
|||||||
|
|
||||||
val bufferedSource = Source.fromFile(conf.infile())
|
val bufferedSource = Source.fromFile(conf.infile())
|
||||||
|
|
||||||
val customers = Util.getCustomers(bufferedSource)
|
val customers = HHCSim2.getCustomers(bufferedSource)
|
||||||
bufferedSource.close()
|
bufferedSource.close()
|
||||||
|
|
||||||
val hhc = new HHCSim(epsilonMax = 40, iterations = 10, WLDMax = 10)
|
// import Ordering.Double.IeeeOrdering
|
||||||
val adjList2 =
|
// val hhc = new HHCSim(epsilonMax = 40, iterations = 10, WLDMax = 10)
|
||||||
customers
|
// val adjList2 =
|
||||||
.map(Util.formAdjMatrix)
|
// customers
|
||||||
.map(e => Util.mstUsingPrims2(e))
|
// .map(Util.formAdjMatrix)
|
||||||
.map(_._1)
|
// .map(e => Util.mstUsingPrims2(e))
|
||||||
// .map(e => Util.makeAdjacencyList2(e._1))
|
// .map { case (mst, eps) => Util.removeEdges(mst)(eps) }
|
||||||
adjList2.map(adjl => {
|
// // .map(_._1)
|
||||||
for (i <- 0 until adjl.size) {
|
|
||||||
print(s"$i -> ")
|
// // .map(e => Util.makeAdjacencyList2(e._1))
|
||||||
adjl(i).foreach(e => {
|
// adjList2.map(e => {
|
||||||
print(f"(${e._1}, ${e._2}%.2f), ")
|
// val (mst, rm) = e
|
||||||
})
|
// for (i <- 0 until mst.size) {
|
||||||
println
|
// print(s"$i -> ")
|
||||||
}
|
// mst(i).foreach(e => {
|
||||||
})
|
// print(f"(${e._1}, ${e._2}%.2f), ")
|
||||||
|
// })
|
||||||
|
// println
|
||||||
|
// }
|
||||||
|
|
||||||
|
// println(rm)
|
||||||
|
// })
|
||||||
|
|
||||||
// val fnl2 = hhc.go(customers)
|
// val fnl2 = hhc.go(customers)
|
||||||
// customers.map(println(_))
|
// customers.map(println(_))
|
||||||
|
|
||||||
@ -61,6 +69,82 @@ object Main {
|
|||||||
// println(s"Oops, an error occured. The error message was: $e")
|
// println(s"Oops, an error occured. The error message was: $e")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
val hhc = new HHCSim2(
|
||||||
|
epsilonMax = 40,
|
||||||
|
iterations = 10,
|
||||||
|
WLDMax = 10,
|
||||||
|
customers = customers
|
||||||
|
)
|
||||||
|
|
||||||
|
val x = hhc.go()
|
||||||
|
|
||||||
|
x match {
|
||||||
|
case Left(value) => println(value)
|
||||||
|
case Right(value) =>
|
||||||
|
}
|
||||||
|
|
||||||
|
x.foreach(d => {
|
||||||
|
val (a, b, c, g) = d
|
||||||
|
println(c)
|
||||||
|
|
||||||
|
println
|
||||||
|
|
||||||
|
for (i <- 0 until b.length) {
|
||||||
|
if (!b(i).isEmpty) {
|
||||||
|
print(s"$i ")
|
||||||
|
print(b(i))
|
||||||
|
// edgeMappings
|
||||||
|
// b(i).foreach(e => {
|
||||||
|
// print(f"(${e.toNode}%d, ${e.weight}%.2f), ")
|
||||||
|
// })
|
||||||
|
println
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println
|
||||||
|
|
||||||
|
for (i <- 0 until g.length) {
|
||||||
|
if (!g(i)._2.isEmpty) {
|
||||||
|
print(s"$i ")
|
||||||
|
print(g(i))
|
||||||
|
// edgeMappings
|
||||||
|
// b(i).foreach(e => {
|
||||||
|
// print(f"(${e.toNode}%d, ${e.weight}%.2f), ")
|
||||||
|
// })
|
||||||
|
println
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
a.foreach(e => {
|
||||||
|
if (!e.isEmpty) {
|
||||||
|
print(s"Cluster-$i: ")
|
||||||
|
i += 1
|
||||||
|
e.foreach(f => { print(s"$f ") })
|
||||||
|
println
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
val x2 = hhc.go2()
|
||||||
|
x2.map(_.map(println))
|
||||||
|
|
||||||
|
// x.map(e => {
|
||||||
|
// val (mst, rm) = e
|
||||||
|
// val y = HHCSim2.DFS(0)(mst)
|
||||||
|
// println(y)
|
||||||
|
// for (i <- 0 until mst.size) {
|
||||||
|
// print(s"$i -> ")
|
||||||
|
// mst(i).foreach(e => {
|
||||||
|
// print(f"(${e.toNode}, ${e.weight}%.2f), ")
|
||||||
|
// })
|
||||||
|
// println
|
||||||
|
// }
|
||||||
|
|
||||||
|
// println(rm)
|
||||||
|
// })
|
||||||
|
|
||||||
val coord1 = Coord(3, 4)
|
val coord1 = Coord(3, 4)
|
||||||
println(s"Distance from origin = ${coord1.distance}")
|
println(s"Distance from origin = ${coord1.distance}")
|
||||||
|
|
||||||
|
@ -6,3 +6,5 @@ import util.Util
|
|||||||
case class HHCEdge(v1: Customer, v2: Customer) {
|
case class HHCEdge(v1: Customer, v2: Customer) {
|
||||||
val weight = Util.getHaversineDistance(v1.location, v2.location)
|
val weight = Util.getHaversineDistance(v1.location, v2.location)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class HHCEdge2[T](fromNode: Int, toNode: Int, weight: T)
|
||||||
|
29
src/main/scala/model/Types.scala
Normal file
29
src/main/scala/model/Types.scala
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import scala.collection.immutable.ArraySeq
|
||||||
|
import scala.collection.IndexedSeqView
|
||||||
|
|
||||||
|
trait HHCTypes {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Graph in mutable adjacency matrix form
|
||||||
|
*/
|
||||||
|
type GraphMatrix[T] = Array[Array[T]]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Graph in mutable adjacency list form
|
||||||
|
*/
|
||||||
|
type MutGraph[T] = Array[Array[HHCEdge2[T]]]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Graph in immutable adjacency list form
|
||||||
|
*/
|
||||||
|
type Graph[T] = ArraySeq[List[HHCEdge2[T]]]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of removed edges
|
||||||
|
*/
|
||||||
|
type RemovedEdges[T] = List[HHCEdge2[T]]
|
||||||
|
|
||||||
|
type Clusters = ArraySeq[List[Int]]
|
||||||
|
}
|
395
src/main/scala/sim/HHCSim2.scala
Normal file
395
src/main/scala/sim/HHCSim2.scala
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
package sim
|
||||||
|
|
||||||
|
import model.HHCTypes
|
||||||
|
import scala.reflect.ClassTag
|
||||||
|
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
|
||||||
|
import scala.collection.immutable.ArraySeq
|
||||||
|
import model.HHCEdge2
|
||||||
|
import util.Util
|
||||||
|
import model.Customer
|
||||||
|
import scala.io.BufferedSource
|
||||||
|
import model.Coord
|
||||||
|
import scala.util.Random
|
||||||
|
|
||||||
|
class HHCSim2(
|
||||||
|
private val epsilonMax: Int = 0,
|
||||||
|
private val iterations: Int = 0,
|
||||||
|
private val WLDMax: Float = 0,
|
||||||
|
private val customers: String Either ArraySeq[Customer]
|
||||||
|
) {
|
||||||
|
import HHCSim2._
|
||||||
|
import Ordering.Double.IeeeOrdering
|
||||||
|
def go() = {
|
||||||
|
customers
|
||||||
|
.flatMap(checkEmpty)
|
||||||
|
.map(formAdjMatrix)
|
||||||
|
.map(e => mstUsingPrims(e))
|
||||||
|
.map { case (mst, epsilon) => removeEdges(mst)(epsilon) }
|
||||||
|
.map { case (mstUpdated, removed) => findClusters(mstUpdated)(removed) }
|
||||||
|
.map {
|
||||||
|
case (clusters, edgeMappings, removedEdges) =>
|
||||||
|
groupClusters(clusters, edgeMappings, removedEdges)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def go2() = {
|
||||||
|
val res = go().flatMap(value => {
|
||||||
|
val (clusters, edgeMappings, removed, clusterGroups) = value
|
||||||
|
workloadBalance(clusters, edgeMappings, removed, clusterGroups)
|
||||||
|
})
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
def workloadBalance[N: Numeric](
|
||||||
|
clusters: Clusters,
|
||||||
|
edgeMappings: ArraySeq[List[HHCEdge2[N]]],
|
||||||
|
removedEdges: RemovedEdges[N],
|
||||||
|
groups: ArraySeq[(Int, List[(Int, N)])]
|
||||||
|
) = {
|
||||||
|
customers.map { c =>
|
||||||
|
val k = clusters.size
|
||||||
|
val mutClusters = clusters.toArray
|
||||||
|
val worlkLoads =
|
||||||
|
mutClusters.map(_.map(j => c(j)).foldLeft(0f)((x, y) => x + y.workload))
|
||||||
|
val sortedClusters =
|
||||||
|
mutClusters.map(_.sortWith((x, y) => c(x).workload < c(y).workload))
|
||||||
|
val minWL =
|
||||||
|
c.foldLeft(c(0).workload)(_ min _.workload)
|
||||||
|
val maxWL =
|
||||||
|
c.foldLeft(0f)(_ max _.workload)
|
||||||
|
val WLD = maxWL - minWL
|
||||||
|
if (WLD > WLDMax) {
|
||||||
|
var t = Random.between(((k / 2) + 1), k)
|
||||||
|
while (!mutClusters(t).isEmpty) t = Random.between(((k / 2) + 1), k)
|
||||||
|
val Ds = groups(t)._2(0)
|
||||||
|
mutClusters.updated(Ds._1, t)
|
||||||
|
}
|
||||||
|
for (_ <- 0 until iterations) {
|
||||||
|
// val workloads = clusters.flatMap(_.map(j => c(j)))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def checkAveragePairwiseDistance[T](
|
||||||
|
lst: List[(Int, T)]
|
||||||
|
)(implicit num: Numeric[T]) = {
|
||||||
|
val sum = lst.foldLeft(0)((x, y) => x + num.toInt(y._2))
|
||||||
|
val avg = sum / lst.length
|
||||||
|
if (avg < epsilonMax) true else false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object HHCSim2 extends HHCTypes {
|
||||||
|
import Ordering.Implicits._
|
||||||
|
|
||||||
|
val composed = (formAdjMatrix _)
|
||||||
|
.andThen(e => mstUsingPrims(e))
|
||||||
|
.andThen { case (mst, epsilon) => removeEdges(mst)(epsilon) }
|
||||||
|
.andThen { case (mstUpdated, removed) => findClusters(mstUpdated)(removed) }
|
||||||
|
|
||||||
|
def getCustomers(
|
||||||
|
infile: BufferedSource
|
||||||
|
): String Either ArraySeq[Customer] = {
|
||||||
|
var customers: String Either ArraySeq[Customer] = Right(ArraySeq.empty)
|
||||||
|
val it = infile.getLines
|
||||||
|
@annotation.tailrec
|
||||||
|
def loop(
|
||||||
|
lst: ListBuffer[Customer],
|
||||||
|
iter: Iterator[String]
|
||||||
|
): String Either ListBuffer[Customer] = {
|
||||||
|
if (!iter.hasNext) Right(lst)
|
||||||
|
else {
|
||||||
|
val line = iter.next
|
||||||
|
val arr = line.split(",").map(_.trim)
|
||||||
|
arr match {
|
||||||
|
case Array(latitude, longitude, workLoad) => {
|
||||||
|
val cust =
|
||||||
|
Customer(
|
||||||
|
Coord(latitude.toDouble, longitude.toDouble),
|
||||||
|
workLoad.toFloat
|
||||||
|
)
|
||||||
|
loop(lst += cust, iter)
|
||||||
|
}
|
||||||
|
case _ => {
|
||||||
|
if (arr.mkString.equals(" ") || arr.mkString.contains("\n"))
|
||||||
|
Left("Error newline")
|
||||||
|
else {
|
||||||
|
Left(
|
||||||
|
"Error reading customers from" +
|
||||||
|
s" file - ${arr.mkString(", ")}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
customers = loop(ListBuffer.empty, it).map(_.to(ArraySeq))
|
||||||
|
} catch {
|
||||||
|
case e: NumberFormatException =>
|
||||||
|
customers = Left(
|
||||||
|
s"Expected number but received string ${e.getMessage()}"
|
||||||
|
)
|
||||||
|
case e: NullPointerException =>
|
||||||
|
customers = Left("Input was null")
|
||||||
|
}
|
||||||
|
customers
|
||||||
|
}
|
||||||
|
|
||||||
|
def checkEmpty(
|
||||||
|
customers: IndexedSeq[Customer]
|
||||||
|
): Either[String, IndexedSeq[Customer]] =
|
||||||
|
customers.length match {
|
||||||
|
case 0 => Left("Error input was empty")
|
||||||
|
case _ => Right(customers)
|
||||||
|
}
|
||||||
|
|
||||||
|
def formAdjMatrix(customers: IndexedSeq[Customer]): GraphMatrix[Double] = {
|
||||||
|
val n = customers.length
|
||||||
|
val edges: Array[Array[Double]] = Array.ofDim(n, n)
|
||||||
|
for (i <- 0 until n) {
|
||||||
|
for (j <- i until n) {
|
||||||
|
val weight =
|
||||||
|
Util.getHaversineDistance(
|
||||||
|
customers(i).location,
|
||||||
|
customers(j).location
|
||||||
|
)
|
||||||
|
edges(i)(j) = weight
|
||||||
|
edges(j)(i) = weight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
edges
|
||||||
|
}
|
||||||
|
|
||||||
|
def mstUsingPrims[T: Numeric](
|
||||||
|
edges: GraphMatrix[T]
|
||||||
|
): (Graph[T], T) = {
|
||||||
|
val num = implicitly[Numeric[T]]
|
||||||
|
val n = edges.length
|
||||||
|
val selected: Array[Boolean] = Array.fill(n)(false)
|
||||||
|
|
||||||
|
selected(0) = true
|
||||||
|
|
||||||
|
val adjList =
|
||||||
|
Array.fill(n)(ListBuffer.empty[HHCEdge2[T]])
|
||||||
|
|
||||||
|
var sum = 0
|
||||||
|
var count = 0
|
||||||
|
|
||||||
|
for (_ <- 0 until n - 1) {
|
||||||
|
var min = 999999
|
||||||
|
var x = 0
|
||||||
|
var y = 0
|
||||||
|
for (i <- 0 until n) {
|
||||||
|
if (selected(i) == true) {
|
||||||
|
for (j <- 0 until n) {
|
||||||
|
if (selected(j) == false && edges(i)(j) != 0) {
|
||||||
|
if (min > num.toInt(edges(i)(j))) {
|
||||||
|
min = num.toInt(edges(i)(j))
|
||||||
|
x = i
|
||||||
|
y = j
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum += num.toInt(edges(x)(y))
|
||||||
|
adjList(x) += HHCEdge2(x, y, edges(x)(y))
|
||||||
|
adjList(y) += HHCEdge2(y, x, edges(x)(y))
|
||||||
|
selected(y) = true
|
||||||
|
}
|
||||||
|
val adjList2 = adjList.map(l => {
|
||||||
|
count += 1
|
||||||
|
l.toList
|
||||||
|
})
|
||||||
|
adjList2.foreach(println)
|
||||||
|
(ArraySeq.unsafeWrapArray(adjList2), num.fromInt(sum / count))
|
||||||
|
}
|
||||||
|
|
||||||
|
def removeEdges[N: Ordering](
|
||||||
|
mst: Graph[N]
|
||||||
|
)(epsilon: N): (Graph[N], RemovedEdges[N]) = {
|
||||||
|
|
||||||
|
val removed = ListBuffer.empty[HHCEdge2[N]]
|
||||||
|
|
||||||
|
val result = ArraySeq.tabulate(mst.length) { i =>
|
||||||
|
val (filtered, rm) = mst(i)
|
||||||
|
// .view
|
||||||
|
// .filter(e => (e.fromNode <= e.toNode))
|
||||||
|
.partition(_.weight <= epsilon)
|
||||||
|
|
||||||
|
// val rm2 = rm.filter(e => (e.fromNode <= e.toNode))
|
||||||
|
|
||||||
|
removed ++= rm
|
||||||
|
|
||||||
|
filtered
|
||||||
|
}
|
||||||
|
println
|
||||||
|
result.foreach(println)
|
||||||
|
println
|
||||||
|
(result, removed.toList)
|
||||||
|
}
|
||||||
|
|
||||||
|
def DFS[T: Numeric](start: Int)(graph: Graph[T]) = {
|
||||||
|
val visited = Array.fill(graph.size)(false)
|
||||||
|
val buf = ListBuffer[Int]()
|
||||||
|
def loop(
|
||||||
|
start: Int,
|
||||||
|
graph: Graph[T],
|
||||||
|
visited: Array[Boolean]
|
||||||
|
): Unit = {
|
||||||
|
visited(start) = true
|
||||||
|
buf += start
|
||||||
|
// val iter = graph(start).iterator
|
||||||
|
// while (iter.hasNext) {
|
||||||
|
// val edge = iter.next
|
||||||
|
// if (!visited(edge.toNode))
|
||||||
|
// loop(edge.toNode, graph, visited)
|
||||||
|
// }
|
||||||
|
for (edge <- graph(start)) {
|
||||||
|
if (!visited(edge.toNode))
|
||||||
|
loop(edge.toNode, graph, visited)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop(start, graph, visited)
|
||||||
|
buf.toList
|
||||||
|
}
|
||||||
|
|
||||||
|
def findClusters[T: Numeric](mstUpdated: Graph[T])(
|
||||||
|
removedEdges: RemovedEdges[T]
|
||||||
|
): (Clusters, ArraySeq[List[HHCEdge2[T]]], RemovedEdges[T]) = {
|
||||||
|
val visited = Array.fill[Boolean](mstUpdated.length)(false)
|
||||||
|
var removedEdges2 = removedEdges
|
||||||
|
val egdeMappings =
|
||||||
|
Array.fill(mstUpdated.length)(List.empty[HHCEdge2[T]])
|
||||||
|
val result = ArraySeq.tabulate(mstUpdated.length) { i =>
|
||||||
|
{
|
||||||
|
val buf = ListBuffer[Int]()
|
||||||
|
// mstUpdated(i).isEmpty match {
|
||||||
|
// case true => { lst += i }
|
||||||
|
// case false => {
|
||||||
|
// if (!visited(i)) {
|
||||||
|
// lst ++= DFS(i)(mstUpdated)
|
||||||
|
// for (j <- lst) visited(j) = true
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
visited(i) match {
|
||||||
|
case true => {
|
||||||
|
// val (nds, rms) = assignEdges(List(i), removedEdges2)
|
||||||
|
// egdeMappings(i) = nds
|
||||||
|
// removedEdges2 = rms
|
||||||
|
}
|
||||||
|
case false if (!mstUpdated(i).isEmpty) => {
|
||||||
|
val nodes = DFS(i)(mstUpdated)
|
||||||
|
buf ++= nodes
|
||||||
|
val (nds, rms) = assignEdges(nodes, removedEdges2)
|
||||||
|
removedEdges2 = rms
|
||||||
|
egdeMappings(i) = nds
|
||||||
|
for (j <- nodes) visited(j) = true
|
||||||
|
}
|
||||||
|
case false => {
|
||||||
|
buf += i
|
||||||
|
val (nds, rms) = assignEdges(List(i), removedEdges2)
|
||||||
|
egdeMappings(i) = nds
|
||||||
|
removedEdges2 = rms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.toList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// println(s"Removed edges size: ${removedEdges2.size}")
|
||||||
|
|
||||||
|
// result
|
||||||
|
(result, ArraySeq.unsafeWrapArray(egdeMappings), removedEdges)
|
||||||
|
// (result.filterNot(_.isEmpty), ArraySeq.unsafeWrapArray(egdeMappings), removedEdges)
|
||||||
|
}
|
||||||
|
|
||||||
|
def assignEdges[T: Ordering](
|
||||||
|
nodes: List[Int],
|
||||||
|
removedEdges: RemovedEdges[T]
|
||||||
|
) = {
|
||||||
|
val it = nodes.iterator
|
||||||
|
def loop(
|
||||||
|
nodes: List[Int],
|
||||||
|
removedEdges: RemovedEdges[T],
|
||||||
|
iter: Iterator[Int],
|
||||||
|
edges: List[HHCEdge2[T]]
|
||||||
|
): (List[HHCEdge2[T]], RemovedEdges[T]) = {
|
||||||
|
if (!iter.hasNext) (edges, removedEdges)
|
||||||
|
else if (!edges.isEmpty) (edges, removedEdges)
|
||||||
|
else {
|
||||||
|
val node = iter.next
|
||||||
|
val (filt, rm) =
|
||||||
|
removedEdges.partition(e => e.fromNode == node)
|
||||||
|
// removedEdges.partition(e => e.toNode == node || e.fromNode == node)
|
||||||
|
loop(nodes, rm, iter, filt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// val filtered = ListBuffer.empty[HHCEdge2[T]]
|
||||||
|
// val updated = ListBuffer.empty[HHCEdge2[T]]
|
||||||
|
// for (node <- nodes) {
|
||||||
|
// val (filt, rm) =
|
||||||
|
// removedEdges.partition(e => e.toNode == node || e.fromNode == node)
|
||||||
|
// if (!filtered.isEmpty) {
|
||||||
|
// // return (filt.toList, rm.toList)
|
||||||
|
// } else {
|
||||||
|
// filtered ++= filt
|
||||||
|
// updated ++= rm
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// print(filtered)
|
||||||
|
// (filtered.toList, updated.toList)
|
||||||
|
val (edges, removedEdgesUpdated) =
|
||||||
|
loop(nodes, removedEdges, it, List.empty[HHCEdge2[T]])
|
||||||
|
// val edges2 = edges.sortWith {
|
||||||
|
// case (HHCEdge2(_, _, weight1), HHCEdge2(_, _, weight2)) =>
|
||||||
|
// weight1 < weight2
|
||||||
|
// }
|
||||||
|
(edges, removedEdgesUpdated)
|
||||||
|
}
|
||||||
|
|
||||||
|
def groupClusters[N: Ordering](
|
||||||
|
clusters: Clusters,
|
||||||
|
edgeMappings: ArraySeq[List[HHCEdge2[N]]],
|
||||||
|
removed: RemovedEdges[N]
|
||||||
|
) = {
|
||||||
|
var k = -1
|
||||||
|
val x = ArraySeq.tabulate(edgeMappings.size)(i => {
|
||||||
|
val buf = ListBuffer.empty[(Int, N)]
|
||||||
|
val lst = edgeMappings(i)
|
||||||
|
val y = lst.foreach(e => {
|
||||||
|
if (edgeMappings(e.toNode).isEmpty) {
|
||||||
|
// var buf = ListBuffer.empty[(Int, N)]
|
||||||
|
for (j <- 0 until clusters.size) {
|
||||||
|
for (edge <- clusters(j)) {
|
||||||
|
if (edge == e.toNode)
|
||||||
|
buf += ((j, e.weight))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Left(buf.toList)
|
||||||
|
} else {
|
||||||
|
buf += ((e.toNode, e.weight))
|
||||||
|
}
|
||||||
|
// Right(lst.map {
|
||||||
|
// case HHCEdge2(fromNode, toNode, weight) => (toNode, weight)
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
if (!clusters(i).isEmpty) k += 1
|
||||||
|
// val lst2 = lst.map {
|
||||||
|
// case HHCEdge2(fromNode, toNode, weight) => (toNode, weight)
|
||||||
|
// }
|
||||||
|
// if (buf.isEmpty) lst2 else buf.toList ::: lst2
|
||||||
|
// if (lt.isEmpty) rt else lt
|
||||||
|
(k, buf.toList.sortWith {
|
||||||
|
case ((_, weight1), (_, weight2)) =>
|
||||||
|
weight1 < weight2
|
||||||
|
})
|
||||||
|
})
|
||||||
|
(clusters, edgeMappings, removed, x)
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,8 @@ import com.typesafe.scalalogging.LazyLogging
|
|||||||
import scala.collection.immutable.ArraySeq
|
import scala.collection.immutable.ArraySeq
|
||||||
|
|
||||||
object Util extends LazyLogging {
|
object Util extends LazyLogging {
|
||||||
|
type Graph[T] = IndexedSeq[Seq[(Int, T)]]
|
||||||
|
import Ordering.Implicits._
|
||||||
private val r = 6471.00 // km
|
private val r = 6471.00 // km
|
||||||
|
|
||||||
def toRad(num: Double): Double = {
|
def toRad(num: Double): Double = {
|
||||||
@ -253,6 +255,117 @@ object Util extends LazyLogging {
|
|||||||
(mst, centroids.toIndexedSeq, removed.toIndexedSeq)
|
(mst, centroids.toIndexedSeq, removed.toIndexedSeq)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// def removeEdges[T](mst: IndexedSeq[Seq[(Int, T)]], epsilon: T)(
|
||||||
|
// implicit num: Numeric[T]
|
||||||
|
// ): (IndexedSeq[Seq[(Int, T)]], IndexedSeq[(Int, Int, T)]) = {
|
||||||
|
// // val mutMST = mst.to(Array)
|
||||||
|
// // val n = mst.length
|
||||||
|
// // val removed: mutable.ListBuffer[(Int, Int, T)] = mutable.ListBuffer.empty
|
||||||
|
// val it = mst.iterator
|
||||||
|
|
||||||
|
// @annotation.tailrec
|
||||||
|
// def loop(
|
||||||
|
// mst: IndexedSeq[Seq[(Int, T)]],
|
||||||
|
// removed: Seq[(Int, Int, T)],
|
||||||
|
// epsilon: T,
|
||||||
|
// iter: Iterator[Seq[(Int, T)]],
|
||||||
|
// index: Int
|
||||||
|
// )(
|
||||||
|
// implicit num: Numeric[T]
|
||||||
|
// ): (IndexedSeq[Seq[(Int, T)]], Seq[(Int, Int, T)]) = {
|
||||||
|
// if (!iter.hasNext) {
|
||||||
|
// return (mst, removed)
|
||||||
|
// }
|
||||||
|
// val lst = iter.next
|
||||||
|
// // val filtered = lst.filter(e => {
|
||||||
|
// // val (node, weight) = e
|
||||||
|
// // num.lt(weight, epsilon)
|
||||||
|
// // })
|
||||||
|
// // val rm = lst
|
||||||
|
// // .filter(e => {
|
||||||
|
// // val (node, weight) = e
|
||||||
|
// // num.gt(weight, epsilon)
|
||||||
|
// // })
|
||||||
|
// // .map(e => {
|
||||||
|
// // val (node, weight) = e
|
||||||
|
// // (index, node, weight)
|
||||||
|
// // })
|
||||||
|
|
||||||
|
// val (filtered, rm) = lst.partition(e => {
|
||||||
|
// val (node, weight) = e
|
||||||
|
// num.lt(weight, epsilon)
|
||||||
|
// })
|
||||||
|
// val rm2 = rm.map(e => {
|
||||||
|
// val (node, weight) = e
|
||||||
|
// (index, node, weight)
|
||||||
|
// })
|
||||||
|
// loop(
|
||||||
|
// mst.updated(index, filtered),
|
||||||
|
// removed ++ rm2,
|
||||||
|
// epsilon,
|
||||||
|
// iter,
|
||||||
|
// index + 1
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// // for (i <- 0 until n) {
|
||||||
|
// // // for (j <- 0 until n) {
|
||||||
|
// // // val weight = mutMST(i)(j)._2
|
||||||
|
// // // if (num.gt(weight, epsilon) && weight != 0) {
|
||||||
|
// // // removed += ((i, j, weight))
|
||||||
|
// // // mutMST(i).remove(j)
|
||||||
|
// // // }
|
||||||
|
// // // }
|
||||||
|
|
||||||
|
// // // var j = 0;
|
||||||
|
// // // for ((node, weight) <- mutMST(i)) {
|
||||||
|
// // // if (num.gt(weight, epsilon) && weight != 0) {
|
||||||
|
// // // removed += ((i, j, weight))
|
||||||
|
// // // mutMST(i).remove(j)
|
||||||
|
// // // }
|
||||||
|
// // // j += 1
|
||||||
|
// // // }
|
||||||
|
|
||||||
|
// // mutMST(i) = mutMST(i).filter(e => {
|
||||||
|
// // val (node, weight) = e
|
||||||
|
// // removed += ((i, node, weight))
|
||||||
|
// // num.lt(weight, epsilon)
|
||||||
|
// // })
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // val updated = ArraySeq.unsafeWrapArray(mutMST.map(e => e.toList))
|
||||||
|
// // val updated = ArraySeq.unsafeWrapArray(mutMST)
|
||||||
|
|
||||||
|
// val (updated, removed) =
|
||||||
|
// loop(mst, Seq[(Int, Int, T)](), epsilon, it, 0)
|
||||||
|
|
||||||
|
// (updated, removed.toIndexedSeq)
|
||||||
|
// }
|
||||||
|
|
||||||
|
def removeEdges[N: Ordering](
|
||||||
|
mst: Graph[N]
|
||||||
|
)(epsilon: N): (Graph[N], List[(Int, Int, N)]) = {
|
||||||
|
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
|
val removed = ListBuffer.empty[(Int, Int, N)]
|
||||||
|
|
||||||
|
val result = ArraySeq.tabulate(mst.length) { i =>
|
||||||
|
val (filtered, rm) = mst(i).partitionMap {
|
||||||
|
case (node, weight) =>
|
||||||
|
if (weight <= epsilon)
|
||||||
|
Left((node, weight))
|
||||||
|
else
|
||||||
|
Right((i, node, weight))
|
||||||
|
}
|
||||||
|
|
||||||
|
removed ++= rm
|
||||||
|
|
||||||
|
filtered
|
||||||
|
}
|
||||||
|
|
||||||
|
(result, removed.toList)
|
||||||
|
}
|
||||||
|
|
||||||
def DFS[T](
|
def DFS[T](
|
||||||
start: Int,
|
start: Int,
|
||||||
graph: Array[Array[T]]
|
graph: Array[Array[T]]
|
||||||
@ -341,8 +454,7 @@ object Util extends LazyLogging {
|
|||||||
lst: IndexedSeq[Customer],
|
lst: IndexedSeq[Customer],
|
||||||
iter: Iterator[String]
|
iter: Iterator[String]
|
||||||
): String Either IndexedSeq[Customer] = {
|
): String Either IndexedSeq[Customer] = {
|
||||||
if (!iter.hasNext)
|
if (!iter.hasNext) return Right(lst)
|
||||||
return Right(lst)
|
|
||||||
val line = iter.next
|
val line = iter.next
|
||||||
val arr = line.split(",").map(_.trim)
|
val arr = line.split(",").map(_.trim)
|
||||||
arr match {
|
arr match {
|
||||||
|
Loading…
Reference in New Issue
Block a user