我仍然是Scala的新手(仍在学习它(。我有以下作业,但由于错误"overloaded method value converged with alternatives:
"而无法运行它
完全错误:
KMeans.scala:101:8: overloaded method value converged with alternatives:
(eta: Double,oldMeans: scala.collection.parallel.ParSeq[kmeans.Point],newMeans: scala.collection.parallel.ParSeq[kmeans.Point])Boolean <and>
(eta: Double,oldMeans: scala.collection.Seq[kmeans.Point],newMeans: scala.collection.Seq[kmeans.Point])Boolean
cannot be applied to (Double)
if (!converged(eta)(means, newMeans))
你能帮忙吗?
完整的类是:
package kmeans
import scala.annotation.tailrec
import scala.collection.{Map, Seq, mutable}
import scala.collection.parallel.CollectionConverters._
import scala.collection.parallel.{ParMap, ParSeq}
import scala.util.Random
import org.scalameter._
class KMeans extends KMeansInterface {
def generatePoints(k: Int, num: Int): Seq[Point] = {
val randx = new Random(1)
val randy = new Random(3)
val randz = new Random(5)
(0 until num)
.map({ i =>
val x = ((i + 1) % k) * 1.0 / k + randx.nextDouble() * 0.5
val y = ((i + 5) % k) * 1.0 / k + randy.nextDouble() * 0.5
val z = ((i + 7) % k) * 1.0 / k + randz.nextDouble() * 0.5
new Point(x, y, z)
}).to(mutable.ArrayBuffer)
}
def initializeMeans(k: Int, points: Seq[Point]): Seq[Point] = {
val rand = new Random(7)
(0 until k).map(_ => points(rand.nextInt(points.length))).to(mutable.ArrayBuffer)
}
def findClosest(p: Point, means: IterableOnce[Point]): Point = {
val it = means.iterator
assert(it.nonEmpty)
var closest = it.next()
var minDistance = p.squareDistance(closest)
while (it.hasNext) {
val point = it.next()
val distance = p.squareDistance(point)
if (distance < minDistance) {
minDistance = distance
closest = point
}
}
closest
}
def classify(points: Seq[Point], means: Seq[Point]): Map[Point, Seq[Point]] = {
means.map{(_, Seq())}.toMap ++ points.groupBy(findClosest(_, means))
}
def classify(points: ParSeq[Point], means: ParSeq[Point]): ParMap[Point, ParSeq[Point]] = {
means.map{(_, ParSeq())}.toMap ++ points.groupBy(findClosest(_, means))
}
def findAverage(oldMean: Point, points: Seq[Point]): Point = if (points.isEmpty) oldMean else {
var x = 0.0
var y = 0.0
var z = 0.0
points.foreach { p =>
x += p.x
y += p.y
z += p.z
}
new Point(x / points.length, y / points.length, z / points.length)
}
def findAverage(oldMean: Point, points: ParSeq[Point]): Point = if (points.isEmpty) oldMean else {
var x = 0.0
var y = 0.0
var z = 0.0
points.seq.foreach { p =>
x += p.x
y += p.y
z += p.z
}
new Point(x / points.length, y / points.length, z / points.length)
}
def update(classified: Map[Point, Seq[Point]], oldMeans: Seq[Point]): Seq[Point] = {
oldMeans.par.map(oldMean => findAverage(oldMean, classified(oldMean)))
}
def update(classified: ParMap[Point, ParSeq[Point]], oldMeans: ParSeq[Point]): ParSeq[Point] = {
oldMeans.par.map(oldMean => findAverage(oldMean, classified(oldMean)))
}
def converged(eta: Double, oldMeans: Seq[Point], newMeans: Seq[Point]): Boolean = {
(oldMeans zip newMeans)
.forall(entry => entry._1.squareDistance(entry._2) <= eta)
}
def converged(eta: Double, oldMeans: ParSeq[Point], newMeans: ParSeq[Point]): Boolean = {
(oldMeans zip newMeans)
.forall(entry => entry._1.squareDistance(entry._2) <= eta)
}
@tailrec
final def kMeans(points: Seq[Point], means: Seq[Point], eta: Double): Seq[Point] = {
val meansClassification = classify(points, means)
val newMeans = update(meansClassification, means)
if (!converged(eta)(means, newMeans))
kMeans(points, newMeans, eta)
else
newMeans
}
@tailrec
final def kMeans(points: ParSeq[Point], means: ParSeq[Point], eta: Double): ParSeq[Point] = {
val meansClassification = classify(points, means)
val newMeans = update(meansClassification, means)
if (!converged(eta)(means, newMeans))
kMeans(points, newMeans, eta)
else
newMeans
}
}
/** Describes one point in three-dimensional space.
*
* Note: deliberately uses reference equality.
*/
class Point(val x: Double, val y: Double, val z: Double) {
private def square(v: Double): Double = v * v
def squareDistance(that: Point): Double = {
square(that.x - x) + square(that.y - y) + square(that.z - z)
}
private def round(v: Double): Double = (v * 100).toInt / 100.0
override def toString = s"(${round(x)}, ${round(y)}, ${round(z)})"
}
object KMeansRunner {
val standardConfig = config(
Key.exec.minWarmupRuns -> 20,
Key.exec.maxWarmupRuns -> 40,
Key.exec.benchRuns -> 25,
Key.verbose -> true
) withWarmer(new Warmer.Default)
def main(args: Array[String]): Unit = {
val kMeans = new KMeans()
val numPoints = 500000
val eta = 0.01
val k = 32
val points = kMeans.generatePoints(k, numPoints)
val means = kMeans.initializeMeans(k, points)
val seqtime = standardConfig measure {
kMeans.kMeans(points, means, eta)
}
val parPoints = points.par
val parMeans = means.par
val partime = standardConfig measure {
kMeans.kMeans(parPoints, parMeans, eta)
}
// Additional `println` to avoid bad interaction with JLine output
println()
println()
println()
println()
println(s"sequential time: $seqtime")
println(s"parallel time: $partime")
println(s"speedup: ${seqtime.value / partime.value}")
println()
println()
println()
}
// Workaround Dotty's handling of the existential type KeyValue
implicit def keyValueCoerce[T](kv: (Key[T], T)): KeyValue = {
kv.asInstanceOf[KeyValue]
}
}
界面:
package kmeans
import scala.collection.{Map, Seq}
import scala.collection.parallel.{ParMap, ParSeq}
/**
* The interface used by the grading infrastructure. Do not change signatures
* or your submission will fail with a NoSuchMethodError.
*/
trait KMeansInterface {
def classify(points: Seq[Point], means: Seq[Point]): Map[Point, Seq[Point]]
def classify(points: ParSeq[Point], means: ParSeq[Point]): ParMap[Point, ParSeq[Point]]
def update(classified: Map[Point, Seq[Point]], oldMeans: Seq[Point]): Seq[Point]
def update(classified: ParMap[Point, ParSeq[Point]], oldMeans: ParSeq[Point]): ParSeq[Point]
def converged(eta: Double, oldMeans: Seq[Point], newMeans: Seq[Point]): Boolean
def converged(eta: Double, oldMeans: ParSeq[Point], newMeans: ParSeq[Point]): Boolean
def kMeans(points: Seq[Point], means: Seq[Point], eta: Double): Seq[Point]
def kMeans(points: ParSeq[Point], means: ParSeq[Point], eta: Double): ParSeq[Point]
}
该方法应调用为converged(eta, means, newMeans)
而不是converged(eta)(means, newMeans)
。如果您查看,这两个def converged
都是使用单个参数列表(具有 3 个参数(定义的,而不是使用两个参数定义的。
此错误最相关的部分不是您引用的部分,而是
不能应用于(双精度(