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);
}
The problem is the following:
clone
an array of primitives, the array object and its values are cloned.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?
wtour
value seems to be an array containing primitiveint
s, so the first of the two cases above applies. I.e. both the array and it's contents are effectively copied.w
value however seems to be a multidimensional array ofint
s. 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: