I would like to implement a multi-objective knapsack problem with two knapsacks in Jenetics, but I struggle with some typing issues. I had a look at the DTLZ1
problem from the Jenetics manual—which is to my knowledge the only MOO example available—and mapped it to the Problem
class:
public class DTLZ1 implements Problem<double[], DoubleGene, Vec<double[]>> {
// Constants...
public static void main(String[] args) {
// Engine setup and evolution stream execution...
}
@Override
public Function<double[], Vec<double[]>> fitness() {
// Original fitness function...
}
@Override
public Codec<double[], DoubleGene> codec() {
// Original codec...
}
}
I have previously implemented a single-objective knapsack problem in Scala using the following type signature (converted to Java):
Problem<ISeq<BitGene>, BitGene, Integer>
Where:
<ISeq<BitGene>
: a knapsack as a (immutable) sequence of bits.BitGene
: the gene type of the evolution engine.Integer
: the fitness of the knapsack, i.e., its profit.Using two knapsacks, I thought about something like (based on the DTLZ1
example):
Problem<ISeq<BitGene>[], BitGene, Vec<int[]>>
Where:
ISeq<BitGene>[]
: multiple knapsacks as (immutable) sequences of bits, wrapped in an array.BitGene
: the gene type of the evolution engine (same as above).int[]
: the fitness of the knapsacks, i.e., their profit.Apart from ISeq<BitGene>[]
, which takes some time getting used to (could I also use List
or something similar?), I don't know how to create a proper codec:
@Override
public Codec<ISeq<BitGene>[], BitGene> codec() {
return Codecs.ofVector(
() -> {
// What kind of supplier do I need?
},
NUMBER_OF_KNAPSACKS);
}
If I understand your problem correctly, the codec would look like this:
public static <T> Codec<ISeq<ISeq<T>>, BitGene>
codec(final ISeq<? extends T> items, final int knapsackCount) {
return Codec.of(
Genotype.of(
BitChromosome.of(items.length()).instances()
.limit(knapsackCount)
.collect(ISeq.toISeq())
),
gt -> gt.stream()
.map(ch -> ch.as(BitChromosome.class))
.map(ch -> ch.ones()
.<T>mapToObj(items)
.collect(ISeq.toISeq()))
.collect(ISeq.toISeq())
);
}
Instead of an ISeq<T>[]
array, I'm using a ISeq<ISeq<T>>
, but the size of the first sequence will be knapsackCount
and the size of the nested sequence is itmes.length()
. The signature of your problem will be Problem<ISeq<ISeq<T>>, BitGene, Vec<double[]>>
.