1

私は遺伝的アルゴリズムライブラリを設計しており、現在Genomeクラスを構築しています。このクラスには、ゲノムの作成、突然変異、交差、および評価のためのいくつかのメソッドが含まれており、このライブラリの中心となります。この抽象クラスには、 と の 2 つのサブクラスがStaticGenomeありVariableGenomeます。これらのクラスは、固定長または可変長のゲノムに追加機能を提供します。

最終的に、任意の 2 つのゲノムの交差は、ゲノム タイプとは無関係である必要があります。そうは言っても、このメソッドは 2 つのゲノムを取り込み、2つの親ゲノムの特別な組み合わせであるsinglePointCrossover(Genome parent2)新しいオブジェクトを返します。Genomeただし、Genome抽象クラスであるため、新しいGenomeオブジェクトを子孫としてインスタンス化することはできません。

スーパークラスから、サブクラスと同じ型の新しいオブジェクトを返すにはどうすればよいですか?

どんな援助でも大歓迎です。

Genomeクラス:

public abstract class Genome <ElementType> {
    private String name;
    private List<AbstractGenomeElement<ElementType> > elements;

    // Mutation Methods //////////////////////////////////////////////
    public AbstractGenomeElement<ElementType> mutateElement(AbstractGenomeElement<Integer> element) {
        return this.mutateElementAtIndex(this.getElements().indexOf(element));
    }

    public AbstractGenomeElement<ElementType> mutateElementAtIndex(int i) {
        return this.getElement(i).mutate();
    }

    // Crossover Methods //////////////////////////////////////////////
    public Genome<ElementType> singlePointCrossover(Genome<ElementType> genome2){
        return multiPointCrossover(genome2, 1);
    }

    public Genome<ElementType> twoPointCrossover(Genome<ElementType> genome2){
        return multiPointCrossover(genome2, 2);
    }

    public Genome<ElementType> multiPointCrossover(Genome<ElementType> genome2, int crosses){
        List<AbstractGenomeElement<ElementType>> newElements= new ArrayList<AbstractGenomeElement<ElementType>>();
        Integer nums[] = new Integer[length-1];

        for (int i = 0; i < length-1; i++) { nums[i] = i+1; }

        List<Integer> shuffled = Arrays.asList(nums);
        Collections.shuffle(shuffled);
        shuffled = shuffled.subList(0, crosses);
        boolean selectFromParentA = true;
        for(int i = 0; i < length; i++){
            if(shuffled.contains((Integer)i)){
                selectFromParentA = !selectFromParentA;
            }
            if(selectFromParentA) newElements.add(this.getElement(i));
            else newElements.add(genome2.getElement(i));
        }
        // Code fails at this point. "Can not instantiate the type Genome"
        return new Genome<ElementType>(name, newElements);
    }
}

2 つのサブクラス:

public class StaticGenome<ElementType> extends Genome<ElementType> {

}

public class VariableGenome<ElementType> extends Genome<ElementType> {

}

そして、私がテストに使用している主な方法:

public static void main(String [] args){
    Genome<IntegerElement> genomeA = new StaticGenome<IntegerElement>("Genome A", 50);
    Genome<IntegerElement> genomeB = new StaticGenome<IntegerElement>("Genome B", 50);

    Genome<IntegerElement> offspring = genomeB.uniformCrossover(genomeA.elementCrossover(genomeA.multiPointCrossover(genomeB, 3)));
    offspring.setName("Offspring");
    System.out.println(offspring);
}
4

4 に答える 4

1

私が正しければ、問題は次のとおりです。Genomeオブジェクト (抽象クラスのサブクラスGenome) が与えられた場合、そのサブクラスの新しいインスタンスをどのようにインスタンス化できますか?

まあ、これが最善の方法かどうかはわかりませんが、私が思いついたのは次のとおりです。

public Genome<ElementType> 
multiPointCrossover(Genome<ElementType> genome2, int crosses){
    // Snip...
    Genome g;
    try {
        g = genome2.getClass()
                .getConstructor(String.class, List.class)
                .newInstance();
    } catch (Exception e) {
        // Can throw quite a few exceptions...
    }
    return g;
}

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getConstructor(java.lang.Class...) http://docs.oracle.com/javase /1.5.0/docs/api/java/lang/reflect/Constructor.html#newInstance(java.lang.Object...)

注: Dev Blanked のソリューションの方がクリーンで使いやすいと思います。これは、彼らが投稿したときに私が思いついたものです。

于 2013-05-05T06:05:00.390 に答える
1

オーバーライドされたメソッドからサブクラスを返すことができます。これは共変の戻り型と呼ばれます

abstract class Genome {
    abstract Genome singlePointCrossover(Genome parent2); 
}

class StaticGenome extends Genome {
    @Override
    StaticGenome singlePointCrossover(Genome parent2) {
        ...
    }
}

class VariableGenome extends Genome {
    @Override
    VariableGenome singlePointCrossover(Genome parent2) {
        ...
    }
}
于 2013-05-05T05:30:44.317 に答える
0

Genome クラスと Static/VariableGenome クラスの間にもう 1 つクラスを導入する必要があると思います。私は微生物学の専門家ではないので、適切な論理名を推奨することはできません. しかし、Genome の新しい子クラス (newGenomeClass としましょう) があり、Static/VriablGenome クラスの親として機能する場合は、次のようなメソッドを使用できます。

public newGenomeClass singlePointCrossover(newGenomeClass parent1,newGenomeClass parent2).

それが役に立てば幸い!

于 2013-05-05T05:28:02.703 に答える