helisa icon indicating copy to clipboard operation
helisa copied to clipboard

java.lang.IllegalStateException: Can't convert this genotype: [[Predictor()]]

Open milosrs opened this issue 6 years ago • 2 comments

I hope I can get some help here, because I can't find any related issues by googling.

I have a case class that consists of 30 fields. All these field types are IntegerGene-s. The class doesn't extend any chromosome type.

case class Predictor() {
  var f1: IntegerGene = IntegerGene.of(3, 50)
  var f2: IntegerGene    = IntegerGene.of(0, 1)
  var f3: IntegerGene = IntegerGene.of(10, 200)
  //..... so on
}

I have a case class that represents it's performance called PredictorResult

case class PredictorResult() {
  var side: String = ""
  var open: Double = 0
  var close: Double = 0
  var units: Int = 0
  var high: Double = 0
  var low: Double = 0
}

I'm trying to use the Helisa framework like below, but when trying to get the best phenotype, I get the error I provided to you.

  def generatePredictor(): Predictor = new Predictor()

  def validatePredictor(predictor: Predictor): Boolean = {
   PredictorValidator.validate(predictor)
  }

  val genotype = () => genotypes.uniform(chromosomes.any(() => generatePredictor(), validatePredictor))

 private val evolver = Evolver(fitness, genotype)
    .populationSize(15)
    .selector(new RouletteWheelSelector())
    .geneticOperators(new UniformCrossover(), new SwapMutator(0.3))
    .build()

  val bestPhenotype = evolver.streamScalaStdLib().head.bestPhenotype

  def fitness(predictor:Predictor) => {
    val predictorResult: PredictorResult = Rules.applyRulesOnPredictor(
      predictor = predictor,
      economyElements = economyElements,
      examinedPeriod = examinedPeriod,
      enteringPrice = enteringPrice
    )

   (predictorResult.high - predictorResult.low) / predictorResult.high
  }

What am I doing wrong?

milosrs avatar May 21 '19 21:05 milosrs

I had to create a case class Guess(...) in who's constructor I have put all of my Genes as int fields.`Then the evolver started calling the fitness function.

milosrs avatar May 22 '19 22:05 milosrs

@milosrs : Sorry for the late reply.

First of all, it appears that some of the example is in pseudo-code or erroneously truncated code. This makes it difficult to reproduce the issue, since it's likely that what the code the maintainer ends up with might not mirror your exact problem. I appreciate that a working, compiling (or not compiling in the expected way :slightly_smiling_face: ) example is more work for the reporter, but in the end it helps to solve the issue with less communication overhead.

The second issue is that those case classes... aren't really case classes. They're just classes with the case qualifier appended, but internally containing only mutable fields, not constructor-defined fields. Really, the case qualifier here does more harm than good, as it generates totally incorrect hashCode and equals.

In general, the problems are:

  • the fitness function should be defined on the phenotype, i.e. PredictorResult, and not Predictor.
  • PredictorResult should be an actual case class, i.e. case class PredictorResult(side: String = "", open: Double = 0,...). The tools that helisa uses for conversion rely on the properties of case classes to work correctly.
    • BTW, shapeless is used pretty much by almost everything for auto-derivation in the Scala world, so I strongly recommend to read up on the hows and whys of case classes. Will save you a lot of pain in the long run :).
  • the genotype Predictor and phenotype PredictorResult should also have the same number, sequence, and type of fields. Sorry the message does not specify that in detail, this is still somewhat of a WIP. If you need more fields outside of your GA run, you can convert to another class manually, or via e.g. chimney.
  • you have a different structure for you genotype and phenotype. Your phenotype is an object with n fields. Your genotype is an object that contains and object with n fields. I'm not sure how you got this working actually, so would be interested in seeing that :slightly_smiling_face: .

Again, sorry for the late reply, and hope it helps.

mikolak-net avatar Jun 19 '19 18:06 mikolak-net