序列上的通用操作

时间:2016-05-06 19:01:00

标签: scala collections types covariance

我正在研究这个简单的项目,我想制作一个遗传算法来找到某个适应度函数的近似最优值。简而言之,它看起来像这样:

class Individual[T](val underlying: T, val fitnessFunc: T => Double) {
    lazy val fitness: Double = fitnessFunc(underlying)
    def update(x: T): Individual[T] = new Individual[T](x, fitnessFunc)
}

class Population[T](individuals: Seq[Individual[T]]) {
    def best: Individual[T] = individuals.tail.foldLeft(individuals.head)((b, a) => if(b.fitness > a.fitness) b else a) // not sure if this is the best way btw
}

trait GeneticAlgorithm[T] {
    def select(p: Population[T]): Individual[T]
    def crossover(i1: Individual[T], i2: Individual[T]): (Individual[T], Individual[T])
    def mutate(i: Individual[T]): Individual[T]
    def evolve(p: Population[T]): Population[T] {
        ...
    }
}

这样我就可以专门为某个类型GeneticAlgorithm创建T的实现。我现在正在忙于创建一些选择,交叉和变异策略的实现。

T是一个序列时,我遇到了问题。对于这种类型,我希望有一个变异策略,例如,只是一个随机的随机播放:

object Mutation {
    def shuffleVector(p: Double): Individual[Vector[_]] => Individual[Vector[_] = (i: Individual[Vector[_]) => {
        if (math.random < p) i.update(scala.util.Random.shuffle(i.underlying)) else i
    }
}

除了它特定于Vector而不是任何序列之外,它编译得很好。我使用存在类型的原因是我不关心Vector的类型。

但是当我想使用它时,我遇到了问题。例如,当我想优化一个向量的向量时:

val ga = new GeneticAlgorithm[Vector[Int]] {
    ...
    override def mutate(i: Individual[Vector[Int]]): Individual[Vector[Int]] = Mutation.shuffleVector(0.5)(i)
    ...
}

我收到错误:Expression of type Individual[Vector[_]] doesn't conform to expected type Individual[Vector[Int]]

除了可以解决的其他一些问题外,解决这个问题的正确方法是什么?我怀疑它必须做一些覆盖面,但还不确定。一直在忙着学习斯卡拉的方式......; - )

2 个答案:

答案 0 :(得分:2)

首先,不是你问的,而是......

individuals.tail.foldLeft(individuals.head)((b, a) => if(b.fitness > a.fitness) b else a)

something.tail.foldLeft(something.head)(f)相当于something.reduce(f)

此外,您的代码段实际上等同于individuals.maxBy(_.fitness)

现在,为了回答你的问题,解决方案很简单:只需使你的随机函数通用:

def maybeShuffle[T](p: Double, xs: Seq[T]): Seq[T] = 
  if(math.random < p) scala.util.Random.shuffle(xs) else xs

答案 1 :(得分:0)

这实际上可能是这些情况之一,使用下划线作为存在类型的简写实际上并没有产生明显的结果。

Individual[Vector[_]] 

被翻译为

Individual[Vector[T]] forSome {type T} 

不同
Individual[Vector[T] forSome {type T}] 

这可能是你的想法。

我认为如果你改变方法的签名,那么错误就会消失。