So I've been tasked to work on an algorithm based on Random Mutation Hill Climbing. I have a method RMHC that takes in an ArrayList of weights and two ints, one for number of weights and another for iterations. My instructions tell me to create an initial solution, copy it and then apply a mutation method SmallChange() to the initial solution. I was also instructed on how to copy the solution with the GetSol() method in my ScalesSolution class. The mutation takes in a binary String value (i.e 11101) and changes a random substring in the binary to either 0 or 1 so I may be met with an output such as 10101 if the 2nd substring is mutated.
My issue is that when I make the SmallChange() to my solution, it makes the change to the original solution also.
I've already tried adding a copy constructor as what was suggested in another question I'd found, but it did not work.
Main Method
public class Worksheet9 {
public static void main(String[] args) {
ArrayList<Double> myArray = new ArrayList<Double>();
myArray.add(1.0);
myArray.add(2.0);
myArray.add(3.0);
myArray.add(4.0);
myArray.add(10.0);
RMHC(myArray, 5, 2);
}
RMHC Method
public static ScalesSolution RMHC(ArrayList<Double> weights,int n,int iter)
{
ScalesSolution oldsol = new ScalesSolution(n);
ScalesSolution newsol = new ScalesSolution(oldsol.GetSol());
//Attempting Copy Constructor
ScalesSolution newsol = new ScalesSolution(oldsol);
double origfitness = oldsol.ScalesFitness(weights);
System.out.println("Original Fitness: " + origfitness);
double origfitness1 = newsol.ScalesFitness(weights);
System.out.println("Cloned Original Fitness: " + origfitness1);
newsol.SmallChange();
double origfitness2 = newsol.ScalesFitness(weights);
System.out.println("Changed Fitness: " + origfitness2);
double origfitness3 = oldsol.ScalesFitness(weights);
System.out.println("Cloned Original Fitness: " + origfitness3);
return(oldsol);
}
}
ScalesSolution Class
import java.util.ArrayList;
import java.util.Random;
public class ScalesSolution
{
private static String scasol;
//Creates a new scales solution based on a string parameter
//The string parameter is checked to see if it contains all zeros and ones
//Otherwise the random binary string generator is used (n = length of parameter)
#
public ScalesSolution(ScalesSolution another) {
this.scasol = another.scasol; // you can access
}
public void SmallChange() {
int n = scasol.length();
String s = scasol;
Random rand = new Random();
int p = (rand.nextInt(n));
String x;
x = scasol.substring(0, p);
if (scasol.charAt(p) == '0') {
x += '1';
} else {
x += '0';
}
x += scasol.substring(p + 1, n);
scasol = x;
}
public String GetSol()
{
return(scasol);
}
public ScalesSolution(String s)
{
boolean ok = true;
int n = s.length();
for(int i=0;i<n;++i)
{
char si = s.charAt(i);
if (si != '0' && si != '1') ok = false;
}
if (ok)
{
scasol = s;
}
else
{
scasol = RandomBinaryString(n);
}
}
private static String RandomBinaryString(int n)
{
String s = new String();
//Code goes here
//Create a random binary string of just ones and zeros of length n
for(int i = 0; i < n; i++){
int x = CS2004.UI(0, 1);
if(x == 0){
s += '0';
} else if (x == 1) {
s += '1';
}
}
return(s);
}
public ScalesSolution(int n)
{
scasol = RandomBinaryString(n);
}
//This is the fitness function for the Scales problem
//This function returns -1 if the number of weights is less than
//the size of the current solution
public static double ScalesFitness(ArrayList<Double> weights)
{
if (scasol.length() > weights.size()) return(-1);
double lhs = 0.0,rhs = 0.0;
int n = scasol.length();
for(int i = 0; i < n; i++){
if (scasol.charAt(i) == '0') {
lhs += weights.get(i);
}
else {
rhs += weights.get(i);
}
}
//Code goes here
//Check each element of scasol for a 0 (lhs) and 1 (rhs) add the weight wi
//to variables lhs and rhs as appropriate
return(Math.abs(lhs-rhs));
}
//Display the string without a new line
public void print()
{
System.out.print(scasol);
}
//Display the string with a new line
public void println()
{
print();
System.out.println();
}
}
When I call the RMHC function in the main method, I get an output like this:
Original Fitness: 16.0
Cloned Original Fitness: 16.0
Changed Fitness: 14.0
Cloned Original Fitness: 14.0
The 2nd Cloned Original Fitness should also be value 16.0 in this example. Once I figure out this initial issue, I will implement the code into a for loop to include the iterations. Thanks.
scasolmessing you up. There's only one in your program so you "can't" make a copy of it.