2016-05-06 17 views
0

Ich arbeite an diesem einfachen Projekt, wo ich einen genetischen Algorithmus machen möchte, um fast optimale Werte für eine bestimmte Fitness-Funktion zu finden. Kurz gesagt sieht es so etwas wie diese:Generische Operationen auf Sequenzen

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

Auf diese Weise ich T eine Implementierung der GeneticAlgorithm speziell für eine bestimmte Art zu schaffen. Ich bin gerade damit beschäftigt, einige Implementierungen von Selektions-, Crossover- und Mutationsstrategien zu erstellen.

Ich bin jedoch in Probleme geraten, wenn T eine Sequenz ist. Für diese Art ich eine Mutation-Strategie haben will, die, zum Beispiel, nur eine zufällige Shuffle mit einer gewissen Chance:

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

Abgesehen von der Tatsache, dass es spezifisch Vektor ist und keine Sequenz, kompiliert Alles gut. Der Grund, warum ich existentielle Typen verwendet habe, ist, dass es mir egal ist, aus welchem ​​Typ der Vektor besteht.

Wenn ich es jedoch verwenden will, stoße ich auf Probleme. Zum Beispiel, wenn ich will ein Foto von ints optimieren:

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

ich den Fehler: Expression of type Individual[Vector[_]] doesn't conform to expected type Individual[Vector[Int]].

Abgesehen von einigen anderen Dingen, die behoben werden können, was ist der richtige Weg, um dies zu lösen? Ich vermute, dass es etwas mit Deckung zu tun hat, aber noch nicht sicher. Sie waren bereits damit beschäftigt, die Scala Möglichkeiten zu lernen ... ;-)

Antwort

2

Vor allem nicht, dass Sie gefragt, aber ...

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

something.tail.foldLeft(something.head)(f) entspricht something.reduce(f).

Außerdem ist Ihre Snippet tatsächlich entspricht individuals.maxBy(_.fitness)

, nun Ihre Frage zu beantworten, die Lösung ist einfach: Ihre Shuffle-Funktion machen generic:

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

Ja, das ist in der Tat die offensichtlichste Lösung. Vielen Dank. – avanwieringen

0

Dies könnte tatsächlich einer von diesen sein Fälle, in denen die Verwendung des Unterstrichs als Kürzel für den existentiellen Typ tatsächlich nicht zu dem offensichtlichen Ergebnis führt.

Individual[Vector[_]] 

wird übersetzt

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

, die von

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

unterscheidet was wahrscheinlich ist, was Sie im Kopf haben.

Ich denke, dass wenn Sie die Signatur der Methode ändern, wird der Fehler verschwinden.