Как определить характеристики для генома? - PullRequest
1 голос
/ 15 сентября 2011

Есть ли в ИИ простые и / или очень наглядные примеры того, как можно внедрить геном в симуляцию?

По сути, я прошёл простое пошаговое руководство (не учебник, а скорее что-то вроде обобщающего характера), в котором подробно рассказывается, как реализовать геном, который изменяет характеристики у «индивида» в суммировании.

Эти гены не будут такими, как:

  • Масса
  • Сила
  • Длина
  • Etc ..

Но скорее они должны быть вещами , определяющими вышеуказанные вещи, абстрагирующими геном от фактических характеристик обитателей симуляции.

Достаточно ли ясно, что я хочу?

В любом случае, если есть какой-то способ, который вы попробовали, это лучше, и это реализует эволюцию в форме, подобной этим сексуальным пловцам , тогда непременно отправьте это! Чем веселее вдохновение, тем лучше:)

1 Ответ

3 голосов
/ 15 сентября 2011

Если вы реализуете свои «индивидуумы» самостоятельно, тогда любой объект может выступать в качестве вашего генома.

Характеристики

Один способ еще больше упростить это - превратить ваши характеристики в перечисления. Таким образом, вы можете иметь простую рекомбинацию генов родителя, выбирая из них признаки и мутацию гена путем случайного выбора одного из значений enum для характеристики.

Как только это сработает, вы можете получить больше нюансов с диапазонами значений, но использование enums помогает мне сначала разобраться.

Фитнес

Затем, чтобы придать этим характеристикам значение, вам нужна функция пригодности, которая описывает производительность. Отношение между характеристиками зависит от вас, поэтому вы можете описать его любым удобным для вас способом. Это просто обеспечивает последовательный способ сравнения двух геномов.

Моделирование

Затем, чтобы запустить симуляцию, просто начните с нескольких родителей и создайте группу детей, чтобы дополнить друг друга. Это, конечно, может быть автоматизировано, но для ясности приведу явный пример.

Пример Java

import java.util.PriorityQueue;

class Genome implements Comparable<Genome> {

    public enum Mass {
        LIGHT(1),
        AVERAGE(2),
        HEAVY(3);

        final Integer value;
        Mass(Integer value) {
            this.value = value;
        }
    }

    public enum Strength {
        WEAK(1),
        AVERAGE(2),
        STRONG(3);

        final Integer value;
        Strength(Integer value) {
            this.value = value;
        }

    }

    public enum Length {
        SHORT(1),
        AVERAGE(2),
        LONG(3);

        final Integer value;
        Length(Integer value) {
            this.value = value;
        }
    }

    private final Mass mass;
    private final Strength strength;
    private final Length length;

    public Genome(Mass mass, Strength strength, Length length) {

            this.mass = mass;
            this.strength = strength;
            this.length = length;
    }

    private Integer fitness() {

        return strength.value * length.value - mass.value * mass.value;
    }

    @Override public int compareTo(Genome that) {

        // notice the fitter is less in precedence
        if(this.fitness() > that.fitness())
            return -1;
        else if(this.fitness() < that.fitness())
            return 1;
        else // this.fitness() == that.fitness()
            return 0;
    }

    public static Genome recombine(Genome... parents) {

        if(parents.length < 1)
            return null;

        // Select parents randomly and then characteristics from them
        Mass mass = parents[(int)(Math.random() * parents.length)].mass;
        Strength strength = parents[(int)(Math.random() * parents.length)].strength;
        Length length = parents[(int)(Math.random() * parents.length)].length;;

        return new Genome(mass, strength, length);
    }

    public static Genome mutate(Genome parent) {

        // Select characteristics randomly
        Mass mass = Mass.values()[(int)(Math.random() * Mass.values().length)];
        Strength strength = Strength.values()[(int)(Math.random() * Strength.values().length)];
        Length length = Length.values()[(int)(Math.random() * Length.values().length)];

        return new Genome(mass, strength, length);
    }

    public static void main() {

        PriorityQueue<Genome> population = new PriorityQueue<Genome>();

        Genome parent1 = new Genome(Mass.LIGHT, Strength.STRONG, Length.SHORT);
        Genome parent2 = new Genome(Mass.AVERAGE, Strength.AVERAGE, Length.AVERAGE);
        Genome parent3 = new Genome(Mass.HEAVY, Strength.WEAK, Length.LONG);

        population.add(parent1);
        population.add(parent2);
        population.add(parent3);

        Genome child1 = Genome.recombine(parent1, parent2);
        Genome child2 = Genome.recombine(parent1, parent2);
        Genome child3 = Genome.recombine(parent1, parent3);
        Genome child4 = Genome.recombine(parent1, parent3);
        Genome child5 = Genome.recombine(parent2, parent3);
        Genome child6 = Genome.recombine(parent2, parent3);
        Genome child7 = Genome.recombine(parent1, parent2, parent3);
        Genome child8 = Genome.recombine(parent1, parent2, parent3);
        Genome child9 = Genome.recombine(parent1, parent2, parent3);

        child1 = Genome.mutate(child1);
        child2 = Genome.mutate(child2);
        child4 = Genome.mutate(child4);
        child8 = Genome.mutate(child8);

        population.add(child1);
        population.add(child2);
        population.add(child3);
        population.add(child4);
        population.add(child5);
        population.add(child6);
        population.add(child7);
        population.add(child8);
        population.add(child9);

        // and the winner is...
        Genome fittest = population.peek();
    }
}

Кодирование

Поскольку звучит так, как будто вы хотите закодировать характеристики в последовательность, в которой некоторые характеристики явно указаны в последовательности, а другие получены из них.

Вы можете сделать это, закодировав ваш ряд значений, как перечисленные выше, в целое число с кусками, представляющими ваши явные характеристики.

Например, если у вас есть две явные характеристики с четырьмя возможными значениями каждая, вы можете закодировать набор как целое число в форме 00XX + XX00. Так, например, 0111 может соответствовать массе 01 и длине 11. То, что это делает, позволяет вам мутировать, изменяя биты в самой последовательности.

Пример Java

import java.util.PriorityQueue;

class Genome implements Comparable<Genome> {

    private final Integer sequence;

    private static final Integer bitmaskChunk = 3; // ...0011

    private static final Integer shiftMass = 0; // ...00XX
    private static final Integer shiftLength = 2; // ...XX00

    private static final Integer shiftModulus = 4; // ...0000

    private Integer getMass() {

        return (sequence >>> shiftMass) & bitmaskChunk;
    }

    private  Integer getLength() {

        return (sequence >>> shiftLength) & bitmaskChunk;
    }

    public Integer getStrength() {

        return getMass() * getLength();
    }

    public Genome(Integer sequence) {

        this.sequence = sequence % (1 << Genome.shiftModulus);
    }

    private Integer fitness() {

        // Some performance measure
        return getStrength() * getLength() - getMass() * getMass();
    }

    @Override public int compareTo(Genome that) {

        // notice the fitter is less in precedence
        if(this.fitness() > that.fitness())
            return -1;
        else if(this.fitness() < that.fitness())
            return 1;
        else // this.fitness() == that.fitness()
            return 0;
    }

    public static Genome recombine(Genome... parents) {

        if(parents.length < 1)
            return null;

        Integer sequence = 0;

        // Select parents randomly and then characteristics from them
        sequence += parents[(int)(Math.random() * parents.length)].getMass() << Genome.shiftMass;
        sequence += parents[(int)(Math.random() * parents.length)].getLength() << Genome.shiftLength;

        return new Genome(sequence);
    }

    public static Genome mutate(Genome parent) {

        Integer sequence = parent.sequence;

        // Randomly change sequence in some way
        sequence *= (int)(Math.random() * (1 << Genome.shiftModulus));

        return new Genome(sequence);
    }

    public static void main() {

        PriorityQueue<Genome> population = new PriorityQueue<Genome>();

        Genome parent1 = new Genome((int)(Math.random() * (1 << Genome.shiftModulus)));
        Genome parent2 = new Genome((int)(Math.random() * (1 << Genome.shiftModulus)));
        Genome parent3 = new Genome((int)(Math.random() * (1 << Genome.shiftModulus)));

        population.add(parent1);
        population.add(parent2);
        population.add(parent3);

        Genome child1 = Genome.recombine(parent1, parent2);
        Genome child2 = Genome.recombine(parent1, parent2);
        Genome child3 = Genome.recombine(parent1, parent3);
        Genome child4 = Genome.recombine(parent1, parent3);
        Genome child5 = Genome.recombine(parent2, parent3);
        Genome child6 = Genome.recombine(parent2, parent3);
        Genome child7 = Genome.recombine(parent1, parent2, parent3);
        Genome child8 = Genome.recombine(parent1, parent2, parent3);
        Genome child9 = Genome.recombine(parent1, parent2, parent3);

        child1 = Genome.mutate(child1);
        child2 = Genome.mutate(child2);
        child4 = Genome.mutate(child4);
        child8 = Genome.mutate(child8);

        population.add(child1);
        population.add(child2);
        population.add(child3);
        population.add(child4);
        population.add(child5);
        population.add(child6);
        population.add(child7);
        population.add(child8);
        population.add(child9);

        // and the winner is...
        Genome fittest = population.peek();
    }
}

Надеюсь, это то, что вы ищете. Удачи.

...