/*******************************************************************************
* Copyright (c) 2009, 2010 Fraunhofer IWU and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Fraunhofer IWU - initial API and implementation
*******************************************************************************/
package net.enilink.commons.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class LinearExtension<T> {
public static void main(String... args) {
IPartialOrderProvider<String> p = new IPartialOrderProvider<String>() {
String[] elements = new String[] { "a1", "a2", "a3", "b1", "b2" };
@Override
public Collection<String> getElements() {
return Arrays.asList(elements);
}
@Override
public Collection<String> getSuccessors(String element) {
if (element == elements[0]) {
return Arrays.asList(elements[1]);
} else if (element == elements[1]) {
return Arrays.asList(elements[2]);
} else if (element == elements[3]) {
return Arrays.asList(elements[4]);
}
return Collections.emptyList();
}
};
LinearExtension<String> leGen = new LinearExtension<String>(p);
leGen.createLinearExtension();
}
IPartialOrderProvider<T> partialOrderProvider;
public LinearExtension(IPartialOrderProvider<T> partialOrderProvider) {
this.partialOrderProvider = partialOrderProvider;
}
private void addSuccessorsToMinElements(T element, Map<T, Integer> predCount,
List<T> minElements) {
for (T succ : partialOrderProvider.getSuccessors(element)) {
Integer inDegree = predCount.remove(succ);
if (inDegree == null) {
continue;
}
inDegree--;
if (inDegree == 0) {
minElements.add(succ);
} else {
predCount.put(succ, inDegree);
}
}
}
public List<T> createLinearExtension() {
return createLinearExtension(new ArrayList<T>());
}
public List<T> createLinearExtension(List<T> list) {
// build mapping of in degrees for each node
Map<T, Integer> predCount = new HashMap<T, Integer>();
List<T> minElements = new LinkedList<T>();
for (T element : partialOrderProvider.getElements()) {
predCount.put(element, 0);
}
for (T element : predCount.keySet()) {
for (T succ : partialOrderProvider.getSuccessors(element)) {
if (element.equals(succ)) {
continue;
}
Integer p = predCount.get(succ);
if (p == null) {
// succ is not contained in
// partialOrderProvider.getElements()
continue;
} else {
p++;
}
predCount.put(succ, p);
}
}
for (Map.Entry<T, Integer> entry : predCount.entrySet()) {
if (entry.getValue().intValue() == 0) {
minElements.add(entry.getKey());
}
}
// create intial topological ordering
while (!minElements.isEmpty()) {
T firstElement = minElements.remove(0);
T secondElement = null;
if (minElements.isEmpty()) {
// linearExt[j] = firstElement
list.add(firstElement);
} else {
secondElement = minElements.remove(0);
// linearExt[j - 1] = firstElement
list.add(firstElement);
// linearExt[j] = secondElement
list.add(secondElement);
}
addSuccessorsToMinElements(firstElement, predCount, minElements);
if (secondElement != null) {
addSuccessorsToMinElements(secondElement, predCount, minElements);
}
}
return list;
}
// boolean isDescendant(T ancestor, T descendant) {
//
// }
//
// public boolean verify(List<T> linearExt) {
// for (int i = 0, max = linearExt.size(); i < max - 1; i++) {
// for (int j = i + 1; j < max; j++) {
// T element_i = linearExt.get(i);
// T element_j = linearExt.get(j);
//
// if (!descendantsMap.get(element_i).contains(element_j)
// && descendantsMap.get(element_j).contains(element_i)) {
// return false;
// }
// }
// }
//
// return true;
// }
}