/*******************************************************************************
* Copyright 2006 - 2012 Vienna University of Technology,
* Department of Software Technology and Interactive Systems, IFS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This work originates from the Planets project, co-funded by the European Union under the Sixth Framework Programme.
******************************************************************************/
package eu.scape_project.planning.model.sensitivity;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import eu.scape_project.planning.model.tree.TreeNode;
/**
* This weight modifier sees the weights as n-dimensional space.
*
* E.g. if you have a node with three children A, B, C it interprets the their weights as three
* dimensional space where the values in each dimension can be 0 <= w <= 1.
*
* Each dimension (=each weight) gets values from (original_value - LIMIT) to (original_value + LIMIT)
* in STEPS steps. Example: let's assume A has the weight 0.35, LIMIT = 0.05 and STEPS = 3. Then A will
* get the following weights: 0.30, 0.35 and 0.40. Of course this is done to B and C as well.
*
* In total there is STEPS^n combinations - the number of iterations grows exponentially with the number of nodes.
*
* @author Jan Zarnikov
*
*/
public class SimpleIterativeWeightModifier implements IWeightModifier {
private int counter = 0;
public static final int STEPS = 2;
public static final double LIMIT = 0.05;
public static final double STEP = (LIMIT * 2) / (STEPS-1);
public boolean performModification(TreeNode node) {
int nodeCount = node.getChildren().size();
// we have NODE_COUNT-dimensional space with STEPS possible values in each dimension
// => STEPS^number-of-nodes combinations
long rounds = (long) Math.pow(STEPS, nodeCount);
List<Long> vector = integerToBinary(counter, STEPS);
for(int nx = vector.size(); nx < nodeCount; nx++) {
vector.add(0, 0L);
}
for(int np = 0; np < nodeCount; np++) {
Long x = vector.get(np);
TreeNode child = node.getChildren().get(np);
double oldWeight = child.getWeight();
double newWeight = oldWeight + (x * STEP -LIMIT);
child.setWeight(newWeight);
}
counter++;
if(counter >= rounds) {
counter = 0;
return false;
} else {
return true;
}
}
/**
* Convert a number to a different base.
*
* Example: integerToBinary(11, 2) = {1, 0, 1, 1}
* (most significat bit first)
*
* @param num
* @param base
* @return
*/
private List<Long> integerToBinary(long num, int base) {
if (num > 0) { //Check to make sure integer is positive.
List<Long> result = integerToBinary(num / base, base);
result.addAll(Collections.singletonList(num % base));
return result;
} else {
return new LinkedList<Long>();
}
}
}