I am writing a simple hillclimber algorithm in C# and am trying the following approach:
Get initial Solution
Copy solution to new object
Apply algorithm to copy
Compare obj value of initial solution with obj value of copy
if better - copy back into initial solution.
I am aware of the fact that this topic has been touched on in a previous post and tried implementing the suggestion there - Using the IClonable class. This is what I have tried:
My Solution Class:
class Solution : ICloneable
{
public Dictionary<Room, List<Patient>> solution { get; set; }
public Solution()
{
solution = new Dictionary<Room, List<Patient>>();
}
public object Clone()
{
return this.MemberwiseClone();
}
}
The algorithm:
public static void swap (Solution solution, Output input, Random rand)
{
Solution intSoln = new Solution();
intSoln = (Solution)solution.Clone();
//Moving things around in intSoln here
Console.WriteLine("new solution = " + objValue(intSoln, input));
Console.WriteLine("old solution = " + objValue(solution, input));
if (objValue(intSoln, input) < objValue(solution, input))
{
solution = (Solution)intSoln.Clone();
}
}
Looking at the printouts for the new and old solutions, they are always the same, which means that obviously the code still copies by reference. I am quite stuck and not sure what to do. Any help would be much appreciated.
MemberwiseClone
will do a shallow copy, which means you'll get a new instance, whose fields have the same references as the initial object.
You want to do a deep copy instead. Here's a copy with one more level:
public object Clone()
{
var copy = new Solution();
foreach (var pair in solution)
copy.solution.Add(pair.Key, pair.Value);
return copy;
}
This will copy the dictionary, but its keys and values will still point to the same instances. So you may perform a deeper copy with something like that:
public object Clone()
{
var copy = new Solution();
foreach (var pair in solution)
copy.solution.Add(new Room(pair.Key), pair.Value.ToList());
return copy;
}
Or:
public object Clone()
{
var copy = new Solution();
foreach (var pair in solution)
copy.solution.Add(new Room(pair.Key), pair.Value.Select(i => new Patient(i)).ToList());
return copy;
}
You need to write some copy constructors for Room
and Patient
for that. Hopefully you get the idea.