package ini.trakem2.analysis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** A class to express a Vertex in a graph.
* This class is stateful and not thread-safe. */
public class Vertex<T> {
public float centrality = 0;
/** Number of short paths passing through this vertex. */
public long sigma = 0; // ALWAYS 1 in a tree
public final Set<Vertex<T>> neighbors = new HashSet<Vertex<T>>();
/** Length of the path. */
public long d = -1;
/** The data associated with this node, if any. */
public T data;
public Vertex(final T data) {
this.data = data;
}
// Temporary variables to use in the computation of centrality
float delta = 0;
final ArrayList<Vertex<T>> predecessors = new ArrayList<Vertex<T>>();
/** All but neighbors. */
protected void reset() {
centrality = 0;
sigma = 0;
d = -1;
//
delta = 0;
predecessors.clear();
}
public int getNeighborCount() {
return neighbors.size();
}
/** Clone a collection of vertices, preserving the neighbors.
* @return An ArrayList of Vertex instances in the same order as @param vs delivered them. */
static public<T> ArrayList<Vertex<T>> clone(final Collection<Vertex<T>> vs) {
final ArrayList<Vertex<T>> copies = new ArrayList<Vertex<T>>(vs.size());
if (1 == vs.size()) {
// neighbors will be empty
copies.add(new Vertex<T>(vs.iterator().next().data));
return copies;
}
final HashMap<Vertex<T>,Vertex<T>> rel = new HashMap<Vertex<T>,Vertex<T>>();
for (final Vertex<T> v : vs) {
rel.put(v, new Vertex<T>(v.data));
}
for (final Vertex<T> v : vs) {
final Vertex<T> copy = rel.get(v);
for (final Vertex<T> w : v.neighbors) {
copy.neighbors.add(rel.get(w));
}
copies.add(copy);
}
return copies;
}
public boolean isBranching() {
return neighbors.size() > 2;
}
public boolean isEnding() {
return 1 == neighbors.size();
}
/** From this vertex to the next branch vertex or end vertex, both inclusive.
* The @param exclude is the neighbor to ignore.
* @throws IllegalArgumentException if @param exclude is not a neighbor. */
public List<Vertex<T>> getBranch(final Vertex<T> parent) {
if (!neighbors.contains(parent)) throw new IllegalArgumentException("'parent' vertex is not a neighbor");
//
final List<Vertex<T>> chain = new ArrayList<Vertex<T>>();
chain.add(this);
if (isBranching()) {
return chain;
}
// Iterate until the next branch or end vertex.
Vertex<T> o = this,
p = parent;
Collection<Vertex<T>> c = this.neighbors;
while (true) {
if (1 == c.size()) {
return chain;
}
for (final Vertex<T> v : c) {
if (v == p) continue;
chain.add(v);
if (v.isBranching() || v.isEnding()) {
return chain;
}
p = o;
o = v;
c = v.neighbors;
}
}
}
}