1

With my GA's crossover method, I keep getting an ArrayOutOfBounds Exception while concatenating the mother's second half to the father's first half. The ArrayList's are all the same size. Why does my mother keep trying to access the 10th element in my list of objects? MyPair is an object with a random direction and random number of steps.

We are currently learning this topic in my A.I. class, so I'm not an expert in GA's yet. Any additional commentary on my crossover algorithm is welcomed.

public static class Chromosome{

        public ArrayList<MyPair> pairs;
        private double x, y;
        public double cost;

        public Chromosome(){
            this.pairs = new ArrayList<MyPair>();
            this.x = 100.0; this.y = 100.0;

//          not sure if I should do this or not
            for(int numPairs = 0; numPairs < 10; numPairs++)
                this.addToChromosome();
        }

        public void addToChromosome(){
            MyPair myPair = new MyPair();
            this.pairs.add(myPair);
        }

        public ArrayList<MyPair> getPairsList(){
            return this.pairs;
        }

        public Chromosome crossOver(Chromosome father, Chromosome mother){

            Chromosome replacement = new Chromosome();
            int pos1 = r.nextInt(father.getPairsList().size());

            while(pos1 >= 10)
                pos1 = r.nextInt(father.getPairsList().size());

            for(int i = 0; i < pos1; i++){
                MyPair tempPair = father.getPairsList().get(i);
                replacement.getPairsList().set(i, tempPair);
            }           

            for(int i = pos1; i < mother.getPairsList().size() - 1; i++){
                MyPair tempPair = mother.getPairsList().get(i);

                // ArrayList keeps trying to set out of bounds here
                replacement.getPairsList().set(i, tempPair);
            }

            return replacement;
        }
manlio
  • 18,345
  • 14
  • 76
  • 126
Kai Tribble
  • 208
  • 1
  • 10

1 Answers1

1

The problem appears to be that you are constructing chromosomes including replacement to have 10 pairs, and then you are setting the element in position i, when i may be 10 or greater.

This has multiple effects you might not have intended. If you splice together a mother and father so that the mother has fewer than 10 pairs, you end up with 10 pairs anyway, with the last ones being just new pairs. If the mother has more than 10 pairs, you are trying to set elements of the arraylist that don't exist, hence you are getting an exception. Another thing you might not have encountered yet is that you haven't copied the information in the pair, you copied the reference to the pair. This means if you give the mother a mutation later by changing the information in the pair rather than replacing a pair, it will affect the child and the child's descendants, which probably is not what you intended.

Instead, start the chromosome with an empty list of pairs, and then add copies of the pairs from the father, and then add copies of pairs from the mother.

Untested code:

public Chromosome crossOver(Chromosome father, Chromosome mother){

    Chromosome replacement = new Chromosome();
    replacement.getPairsList().clear(); // get rid of the original 10 pairs

    int pos1 = r.nextInt(father.getPairsList().size());

    while(pos1 >= 10)
        pos1 = r.nextInt(father.getPairsList().size());

        for(int i = 0; i < pos1; i++){
            MyPair tempPair = father.getPairsList().get(i);
            replacement.getPairsList().add(tempPair.makeCopy()); // appended copy instead of setting ith
        }           

        for(int i = pos1; i < mother.getPairsList().size() - 1; i++){
            MyPair tempPair = mother.getPairsList().get(i);

            // ArrayList keeps trying to set out of bounds here
            replacement.getPairsList().add(tempPair.makeCopy()); // append copy instead of setting ith
        }

        return replacement;
    }

You have to make a makeCopy method in your Pair class that returns a Pair with the same information. There are other ways to do this.

Douglas Zare
  • 3,296
  • 1
  • 14
  • 21
  • Why add a copy of these Pairs as opposed to just appending these Pairs to the end of the list? – Kai Tribble Mar 02 '15 at 16:46
  • The difference is whether they all point to the same Pair object created in the original ancestor, or whether they contain their own information. Suppose your DNA is hit by a cosmic ray and your genetic code mutates, and you get cancer. Does this cause your mother to get the same cancer at the same time? No, because you have **a copy** of your mother's DNA that can mutate independently. If you simply append **references** to your mother's pairs, mutating your DNA would simultaneously mutate your mother's DNA, and your children's DNA, and possibly your brother's DNA, etc. Which do you intend? – Douglas Zare Mar 02 '15 at 17:17
  • Anyway, it wasn't your question, just something else that is likely to go wrong later if you don't change the same part of the code that is generating exceptions. When I made one correction, I pointed out the other problem but you can decide later if it's an issue for you. – Douglas Zare Mar 02 '15 at 17:19
  • Thank you. I'll check back with you after increasing the mutation rate and testing it. – Kai Tribble Mar 02 '15 at 19:27
  • I don't know how the mutation rate is relevant to the problem of getting an index out-of-bounds exception. It sounds like you might want to post another question after this one. Did my answer solve this problem for you? – Douglas Zare Mar 03 '15 at 17:50
  • Yes. Your solution solved my problem. I'll set as the answer. Thank you. – Kai Tribble Mar 03 '15 at 18:11