使用 Jenetics 创建基因型时的约束
Constraints when creating a Genotype using Jenetics
我正在使用 Jenetics 试验多 objective 优化问题 (MOP)。我创建的一个玩具问题是 select 来自给定集合的两个子集,最大化它们的总和,给定每个子集都有一个限制。
但是我想确保这两个子集是互斥的。创建两条染色体的基因型时如何设置此约束?
我用于解决玩具问题的套装是:
private static final ISeq<Integer> SET = ISeq.of( IntStream.rangeClosed( 1, 10 )
.boxed()
.collect( Collectors.toList() ) );
我的问题签名是:
Problem<List<ISeq<Integer>>, BitGene, Vec<int[]>>
编解码器是:
@Override public Codec<List<ISeq<Integer>>, BitGene> codec() {
Objects.requireNonNull( SET );
final Genotype<BitGene> g =
Genotype.of( BitChromosome.of( SET.length() ), BitChromosome.of( SET.length() ) );
return Codec.of(
g,
gc -> gc.stream().map( z -> z.as( BitChromosome.class ).ones().mapToObj( SET )
.collect( ISeq.toISeq() ) ).collect( Collectors.toList() )
);
}
我已经分配了第一个子集的限制为 9,第二个子集的限制为 4。
我期望两个染色体的初始种群具有相互排斥的基因,这样表型最终将产生没有从 SET
复制项目的个体。
我目前得到的示例输出是:
[[4,5], [4]]
但我希望两个人都有相互排斥的物品。 Jenetics 如何实现这一目标?
如果你想要一组不同的基因,你必须定义两个不同的集合。
private static final ISeq<Integer> SET1 = IntStream.rangeClosed(1, 10)
.boxed()
.collect(ISeq.toISeq());
private static final ISeq<Integer> SET2 = IntStream.rangeClosed(11, 20)
.boxed()
.collect(ISeq.toISeq());
public Codec<ISeq<ISeq<Integer>>, BitGene> codec() {
return Codec.of(
Genotype.of(
BitChromosome.of(SET1.length()),
BitChromosome.of(SET2.length())
),
gt -> ISeq.of(
gt.getChromosome(0).as(BitChromosome.class).ones()
.mapToObj(SET1)
.collect(ISeq.toISeq()),
gt.getChromosome(1).as(BitChromosome.class).ones()
.mapToObj(SET2)
.collect(ISeq.toISeq())
)
);
}
有了两个整数集就保证了唯一性。
这不是您问题的唯一可能编码,因为每个问题都有自己的特点。对于多背包问题,我会选择IntegerChromosome
而不是BitChromosomes
。
private static final ISeq<Integer> ITEMS = IntStream.rangeClosed(1, 10)
.boxed()
.collect(ISeq.toISeq());
public Codec<ISeq<List<Integer>>, IntegerGene> codec(final int knapsackCount) {
return Codec.of(
Genotype.of(IntegerChromosome.of(
0, knapsackCount, ITEMS.length())
),
gt -> {
final ISeq<List<Integer>> knapsacks = IntStream.range(0, knapsackCount)
.mapToObj(i -> new ArrayList<Integer>())
.collect(ISeq.toISeq());
for (int i = 0; i < ITEMS.length(); ++i) {
final IntegerGene gene = gt.get(0, i);
if (gene.intValue() < knapsackCount) {
knapsacks.get(gene.intValue()).add(ITEMS.get(i));
}
}
return knapsacks;
}
);
}
上面给出的编解码器选择了一个IntegerChromoses
,长度为背包物品的数量。它的基因范围将大于背包的数量。项目 i 将被放入背包,染色体索引为 IntegerChromosome.get(0, i).intValue()
。如果索引超出有效范围,则跳过该项目。这种编码将保证项目的明确划分。
我正在使用 Jenetics 试验多 objective 优化问题 (MOP)。我创建的一个玩具问题是 select 来自给定集合的两个子集,最大化它们的总和,给定每个子集都有一个限制。 但是我想确保这两个子集是互斥的。创建两条染色体的基因型时如何设置此约束?
我用于解决玩具问题的套装是:
private static final ISeq<Integer> SET = ISeq.of( IntStream.rangeClosed( 1, 10 )
.boxed()
.collect( Collectors.toList() ) );
我的问题签名是:
Problem<List<ISeq<Integer>>, BitGene, Vec<int[]>>
编解码器是:
@Override public Codec<List<ISeq<Integer>>, BitGene> codec() {
Objects.requireNonNull( SET );
final Genotype<BitGene> g =
Genotype.of( BitChromosome.of( SET.length() ), BitChromosome.of( SET.length() ) );
return Codec.of(
g,
gc -> gc.stream().map( z -> z.as( BitChromosome.class ).ones().mapToObj( SET )
.collect( ISeq.toISeq() ) ).collect( Collectors.toList() )
);
}
我已经分配了第一个子集的限制为 9,第二个子集的限制为 4。
我期望两个染色体的初始种群具有相互排斥的基因,这样表型最终将产生没有从 SET
复制项目的个体。
我目前得到的示例输出是:
[[4,5], [4]]
但我希望两个人都有相互排斥的物品。 Jenetics 如何实现这一目标?
如果你想要一组不同的基因,你必须定义两个不同的集合。
private static final ISeq<Integer> SET1 = IntStream.rangeClosed(1, 10)
.boxed()
.collect(ISeq.toISeq());
private static final ISeq<Integer> SET2 = IntStream.rangeClosed(11, 20)
.boxed()
.collect(ISeq.toISeq());
public Codec<ISeq<ISeq<Integer>>, BitGene> codec() {
return Codec.of(
Genotype.of(
BitChromosome.of(SET1.length()),
BitChromosome.of(SET2.length())
),
gt -> ISeq.of(
gt.getChromosome(0).as(BitChromosome.class).ones()
.mapToObj(SET1)
.collect(ISeq.toISeq()),
gt.getChromosome(1).as(BitChromosome.class).ones()
.mapToObj(SET2)
.collect(ISeq.toISeq())
)
);
}
有了两个整数集就保证了唯一性。
这不是您问题的唯一可能编码,因为每个问题都有自己的特点。对于多背包问题,我会选择IntegerChromosome
而不是BitChromosomes
。
private static final ISeq<Integer> ITEMS = IntStream.rangeClosed(1, 10)
.boxed()
.collect(ISeq.toISeq());
public Codec<ISeq<List<Integer>>, IntegerGene> codec(final int knapsackCount) {
return Codec.of(
Genotype.of(IntegerChromosome.of(
0, knapsackCount, ITEMS.length())
),
gt -> {
final ISeq<List<Integer>> knapsacks = IntStream.range(0, knapsackCount)
.mapToObj(i -> new ArrayList<Integer>())
.collect(ISeq.toISeq());
for (int i = 0; i < ITEMS.length(); ++i) {
final IntegerGene gene = gt.get(0, i);
if (gene.intValue() < knapsackCount) {
knapsacks.get(gene.intValue()).add(ITEMS.get(i));
}
}
return knapsacks;
}
);
}
上面给出的编解码器选择了一个IntegerChromoses
,长度为背包物品的数量。它的基因范围将大于背包的数量。项目 i 将被放入背包,染色体索引为 IntegerChromosome.get(0, i).intValue()
。如果索引超出有效范围,则跳过该项目。这种编码将保证项目的明确划分。