/*
*
* Copyright 2012-2013 University Of Southern California
*
* 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.
*
*/
package org.workflowsim.clustering.balancing.metrics;
import java.util.LinkedList;
import java.util.List;
import org.workflowsim.clustering.TaskSet;
/**
* A DistanceVariance
*
* @author Weiwei Chen
* @since WorkflowSim Toolkit 1.0
* @date Apr 9, 2013
*/
public class DistanceVariance implements BalancingMetric {
/**
* Returns the distance variance of a list of taskSets
* @param list the list to be checked
* @return the distance variance
*/
@Override
public double getMetric(List<TaskSet> list) {
if (list == null || list.size() <= 1) {
return 0.0;
}
double sum = 0;
int size = list.size();
int[] distances = new int[size * (size - 1) / 2];
int index = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
TaskSet taskA = list.get(i);
TaskSet taskB = list.get(j);
int distance = calDistance(taskA, taskB);
distances[index] = distance;
index++;
sum += distance;
}
}
double mean = sum / list.size();
sum = 0.0;
for (int i = 0; i < index; i++) {
int distance = distances[i];
sum += Math.pow(distance - mean, 2);
}
return Math.sqrt(sum / list.size());
}
/**
* Calculate the distance between two taskSet
* one assumption here taskA and taskB are at the same level
* because it is horizontal clustering
* does not work with arbitary workflows
* @param taskA
* @param taskB
* @return
*/
private int calDistance(TaskSet taskA, TaskSet taskB) {
if (taskA == null || taskB == null || taskA == taskB) {
return 0;
}
LinkedList<TaskSet> listA = new LinkedList<>();
LinkedList<TaskSet> listB = new LinkedList<>();
int distance = 0;
listA.add(taskA);
listB.add(taskB);
if (taskA.getTaskList().isEmpty() || taskB.getTaskList().isEmpty()) {
return 0;
}
do {
LinkedList<TaskSet> copyA = (LinkedList) listA.clone();
listA.clear();
for (TaskSet set : copyA) {
for (TaskSet child : set.getChildList()) {
if (!listA.contains(child)) {
listA.add(child);
}
}
}
LinkedList<TaskSet> copyB = (LinkedList) listB.clone();
listB.clear();
for (TaskSet set : copyB) {
for (TaskSet child : set.getChildList()) {
if (!listB.contains(child)) {
listB.add(child);
}
}
}
for (TaskSet set : listA) {
if (listB.contains(set)) {
return distance * 2;
}
}
distance++;
} while (!listA.isEmpty() && !listB.isEmpty());
return distance * 2;
}
}