【问题标题】:How to determine characteristics for a genome?如何确定基因组的特征?
【发布时间】:2011-09-15 13:38:16
【问题描述】:

在 AI 中,是否有任何简单和/或非常直观的示例来说明如何将基因组实现到模拟中?

基本上,我正在完成一个简单的演练(不是教程,而是一些总结性质的东西),其中详细说明了如何实现一个基因组,从而改变总和中“个体”的特征。

这些基因不会是这样的:

  • 质量
  • 实力
  • 长度,
  • 等等。

而是它们应该是定义上述事物的事物,从模拟居民的实际特征中抽象出基因组。

我是否足够清楚我想要什么?

无论如何,如果您尝试过任何更好的方法,并且以these sexual swimmers 之类的形式实现进化,那么请务必继续发布!灵感越有趣越好:)

【问题讨论】:

    标签: artificial-intelligence simulation genetic-algorithm genome


    【解决方案1】:

    如果您自己实现“个体”,那么任何对象都可以充当您的基因组。

    特点

    进一步简化此过程的一种方法是将您的特征转换为枚举。通过这种方式,您可以通过从父母基因中选择特征来简单地重组父母的基因,并通过随机选择特征的枚举值之一来对基因进行突变。

    一旦它起作用了,你就可以更细致地了解值范围,但使用枚举可以帮助我一开始就保持清晰。

    健身

    然后,要赋予这些特征含义,您需要一个描述性能的适应度函数。特征之间的关系取决于您,因此您可以用任何有意义的方式来描述它。这只是提供了一种比较两个基因组的一致方法。

    模拟

    然后要运行模拟,只需从几个父母开始,然后生成一堆孩子来完成。这当然可以自动化,但为了清楚起见,这里有一个明确的示例。

    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();
        }
    }
    

    我希望这是您正在寻找的。祝你好运。

    【讨论】:

    • 哇。我希望我可以无限地投票给这个答案,尤其是关于编码听起来非常有用的部分!我想等着把它标记为答案,但它太棒了,我做不到。另外,我相信这些示例是可编译的,不是吗?它们与易于理解的小文本的完美形状段落一样有用,但您可以将它们缩减为最基本的部分。
    • 感谢您的赞赏。是的,这些构建与 Eclipse 中的 JDK 1.6 一样,因此您应该能够将它们用作起点。再次祝你好运。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 2014-08-29
    • 1970-01-01
    • 2016-01-27
    • 2020-07-16
    • 1970-01-01
    相关资源
    最近更新 更多