2016-05-06 3 views
0

Я работаю над этим простым проектом, где хочу сделать генетический алгоритм, чтобы найти почти оптимальные значения для определенной функции пригодности. Короче говоря, он выглядит примерно так:Общие операции над последовательностями

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 
    } 
} 

Помимо того, что он является специфическим для вектора, а не какой-либо последовательности, компилирует просто хорошо. Причина, по которой я использовал экзистенциальные типы, заключается в том, что мне все равно, к какому типу относится вектор.

Когда я хочу использовать его, я сталкиваюсь с проблемами. Например, когда я хочу, чтобы оптимизировать вектор целых чисел:

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]].

Помимо каких-либо других вещей, которые могут быть исправлены, каков правильный способ решить эту проблему? Я подозреваю, что он должен что-то сделать с крышкой, но пока не уверен. Были заняты изучения путей Scala ... ;-)

ответ

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 
+0

Да, это действительно самое очевидное решение. Благодарю. – avanwieringen

0

На самом деле это может быть один из них случаи, когда использование подчеркивания как сокращенного для экзистенциального типа фактически не дает очевидного результата.

Individual[Vector[_]] 

переводится на

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

, который отличается от

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

, который, вероятно, что вы имеете в виду.

Я думаю, что если вы измените подпись метода, ошибка исчезнет.

Смежные вопросы