views:

45

answers:

2

Basically I'm trying to create an implementation of simulated annealing for the multidimensional knapsack problem. I'm having a problem getting the system to decide whether or not to accept a state with a lower value. The annealing is controlled with this function:

while (this.temp > 0)
    {
        System.out.println("Temperature: "+this.temp);
        System.out.println("Current bag: "+bagString(currentBag)+" (Value "+problem.getValue(currentBag)+")");
        next = getNext();
        System.out.println("Next bag: "+bagString(next)+" (Value "+problem.getValue(next)+")");
        if (acceptNext(next))
        {
            System.out.println("Accepted");
            this.currentBag = next;
        } else {
            System.out.println("Not accepted");
        }
        this.temp -= this.delta;
    }

The acceptNext() function decides whether or not to accept the next state, and is defined thus:

public boolean acceptNext(ArrayList<Boolean> next)
{
    if (problem.getValue(next) > problem.getValue(this.currentBag))
    {
        return true;
    } else {
        int loss = (problem.getValue(this.currentBag) - problem.getValue(next));
        double prob = Math.exp(loss/this.temp);
        Random generator = new Random();
        double selection = generator.nextDouble();
        System.out.println("Prob: "+prob+", random number: "+selection);
        if (selection < prob) {
            return true;
        }
        return false;
    }
}

After doing some testing, I found that the currentBag field is assigned to the next value before the acceptNext() function is called. I can't find another "this.currentBag = next" in any of my code. For the sake of completeness, here is the getNext() function:

public ArrayList<Boolean> getNext()
{
    Random generator = new Random();
    boolean valid = false;
    ArrayList<Boolean> next = new ArrayList<Boolean>();
    int j;
    while (!valid)
    {
        next = this.currentBag;
        j = generator.nextInt(problem.getNumObjects());
        if (next.get(j) == true)
        {
            next.set(j, false);
        } else {
            next.set(j, true);
        }
        if (problem.isValid(next))
        {
            valid = true;
        }
    }
    return next;
}

I can't see what is making this value update. Does anyone see anything in the code?

Thanks

Ben

+3  A: 

When you do this, next points to the same thing as current bag, so all changes to next are reflected in currentBag. In your getNext() method:

while (!valid)
{
    next = this.currentBag;
    ...
}

Try this instead:

while (!valid)
{
    next = new ArrayList<Boolean>(this.currentBag);
    ...
}
job
+1  A: 

getNext() sets next to reference the currentBag object and then performs the set operation on it. You need to copy/clone currentBag if you want to then modify the value of next.

Steven Mackenzie