1

I am copying the the current best solution of my program as follows:

public Object clone() 
{   
    MySolution copy = (MySolution)super.clone();
    copy.wtour =    (int[])this.wtour.clone();
    copy.w =        (int[][][][])this.w.clone();

    return copy;
}

When I request the overall best solution in the end, the program always gives me the current best solution but never the one with the best objective value. Also, nothing changes with the solution if I exclude the stated part from my program.

Edit: It is part of a tabu search optimizer that generates solutions and saves new current best solutions (as here) The clone method saves the tours of a routing problem where w[][][][] is a binary decision variable and wtour is a copy of that but consists of the customer numbers in the visiting sequence, i.e. [0, 5, 3, 2, 1, 4].

Edit: I changed my program according to Robby Cornelissen as follows:

    public Object clone()   {   
        MySolution copy = (MySolution)super.clone();
        copy.w = copy2(w);
        return copy;
    } 

    public static int[][][][] copy2(int[][][][] source) {
    int[][][][] target = source.clone();

    for (int i = 0; i < source.length; i++) {
        target[i] = source[i].clone();

        for (int j = 0; j < source[i].length; j++) {
            target[i][j] = source[i][j].clone();

            for (int q = 0; q < source[i][j][q].length; q++) {
                target[i][j][q] = source[i][j][q].clone();

            }
        }
    }

    return target;
}

As a result, i get a clone as follows:

w[0][5][1][0]=1
w[4][2][2][0]=1
w[2][5][3][0]=1
w[5][0][4][0]=1
w[0][4][1][1]=1
w[6][1][2][1]=1
w[1][3][3][1]=1
w[3][0][4][1]=1

The problem now is that only the first element of this belongs to the very best solution (w[0][5][1][0]). Why do the other ones not get copied?

SOLUTION: I changed my program as the provided link suggested to the following:

public Object clone()
{   
    MySolution copy = (MySolution)super.clone();
    copy.w = deepCopyOf(w);
    return copy;
}   // end clone

@SuppressWarnings("unchecked")
public static <T> T[] deepCopyOf(T[] array) {

    if (0 >= array.length) return array;

    return (T[]) deepCopyOf(
            array, 
            Array.newInstance(array[0].getClass(), array.length), 
            0);
}

private static Object deepCopyOf(Object array, Object copiedArray, int index) {

    if (index >= Array.getLength(array)) return copiedArray;

    Object element = Array.get(array, index);

    if (element.getClass().isArray()) {

        Array.set(copiedArray, index, deepCopyOf(
                element,
                Array.newInstance(
                        element.getClass().getComponentType(),
                        Array.getLength(element)),
                0));

    } else {

        Array.set(copiedArray, index, element);
    }

    return deepCopyOf(array, copiedArray, ++index);
}
Community
  • 1
  • 1
Hendrik
  • 153
  • 1
  • 2
  • 18
  • Could you please clarify what the problem is when you run your program? What do you expect to happen, and what is actually happening? What signs indicate a problem? – John D. Jun 12 '15 at 04:09
  • Can you provide details of the class you are trying to clone – Ediac Jun 12 '15 at 04:10
  • Keep in mind also that `clone()` is essentially "broken", so you might want to just roll your own copy solution. – Kayaman Jun 12 '15 at 04:41

1 Answers1

4

The problem is the following:

  • When you clone an array of primitives, the array object and its values are cloned.
  • When you clone an array of objects, the array object is cloned, but the cloned array will contain references to the same objects that were contained in the original array.

Now what does that mean for your case?

  • Your wtour value seems to be an array containing primitive ints, so the first of the two cases above applies. I.e. both the array and it's contents are effectively copied.
  • Your w value however seems to be a multidimensional array of ints. In practice this means that it's actually an array containing array objects, hence the second case applies. Although your top-level array object is copied, the copied array contains references to the same second-level array objects as the original array.

A similar issue and possible solutions are discussed here.

Update

As requested in the comments, a straightforward implementation could look like this. Note that this is completely untested:

public static int[][][] copy(int[][][] source) {
    int[][][] target = source.clone();

    for (int i = 0; i < source.length; i++) {
        target[i] = source[i].clone();

        for (int j = 0; j < source[i].length; j++) {
            target[i][j] = source[i][j].clone();
        }
    }

    return target;
}
Community
  • 1
  • 1
Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156