Skip to content

Commit

Permalink
Median Heuristic implemented
Browse files Browse the repository at this point in the history
Implemented a Median Heuristic that works similarly to the Barycenter
Heuristic. Added the appropriate option called
crossingMinimization.strategy: MEDIAN_LAYER_SWEEP
  • Loading branch information
stu241636 committed Dec 18, 2024
1 parent 099fd0d commit c071a93
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,29 +32,41 @@ public enum CrossingMinimizationStrategy implements ILayoutPhaseFactory<LayeredP
* {@link org.eclipse.elk.alg.layered.options.LayeredOptions.HIERARCHY_HANDLING} is set to
* {@link org.eclipse.elk.core.options.HierarchyHandling.INCLUDE_CHILDREN}, it sweeps into hierarchical graphs
* during the sweep.
* This uses the Barycenter heuristic, in constrast to MEDIAN_LAYER_SWEEP
*/
LAYER_SWEEP,

/**
* This heuristic uses medians of node weights to calculate the correct ordering.
* In all other aspects, it behaves like LAYER_SWEEP.
*/
MEDIAN_LAYER_SWEEP,
/**
* Allow user interaction by considering the previous node positioning. The actual positions
* as given in the input diagram are considered here. This means that if the user moves
* a node, that movement is reflected in the ordering of nodes.
*/
@AdvancedPropertyValue
INTERACTIVE,

/**
* Allows to do no crossing minimization. This requires to also set {@link GreedySwitchType} to off.
*/
NONE;



@Override
public ILayoutPhase<LayeredPhases, LGraph> create() {
switch (this) {
// TODO add new case for median heuristic
// or replace one with median heuristic
case LAYER_SWEEP:
return new LayerSweepCrossingMinimizer(CrossMinType.BARYCENTER);

case MEDIAN_LAYER_SWEEP:
return new LayerSweepCrossingMinimizer(CrossMinType.MEDIAN);

case INTERACTIVE:
return new InteractiveCrossingMinimizer();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,11 @@ public final class InternalProperties {
*/
public static final IProperty<Map<LNode, Integer>> TARGET_NODE_MODEL_ORDER = new Property<>("targetNode.modelOrder");

/**
* The weight of a node as used by the MedianHeuristic class.
*/
public static final IProperty<Double> WEIGHT = new Property<>("medianHeuristic.weight");

/**
* Hidden default constructor.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,6 @@ public class BarycenterHeuristic implements ICrossingMinimizationHeuristic {
/** The Barycenter PortDistributor is used to ask for the port ranks.*/
protected final AbstractBarycenterPortDistributor portDistributor;

/**
* Constructs a Barycenter heuristic for crossing minimization.
*
* @param constraintResolver
* the constraint resolver
* @param random
* the random number generator
* @param portDistributor
* calculates the port ranks for the barycenter heuristic.
* @param graph
* current node order
*/
public BarycenterHeuristic(final ForsterConstraintResolver constraintResolver, final Random random,
final AbstractBarycenterPortDistributor portDistributor, final LNode[][] graph) {
this.constraintResolver = constraintResolver;
this.random = random;
this.portDistributor = portDistributor;
}

/**
* Don't use!
* Only public to be accessible by a test.
Expand All @@ -75,6 +56,7 @@ public void minimizeCrossings(final List<LNode> layer, final boolean preOrdered,
if (randomize) {
// Randomize barycenters (we don't need to update the edge count in this case;
// there are no edges of interest since we're only concerned with one layer)
// simply a permutation of nodes in layer
randomizeBarycenters(layer);
} else {
// Calculate barycenters and assign barycenters to barycenterless node groups
Expand All @@ -88,6 +70,7 @@ public void minimizeCrossings(final List<LNode> layer, final boolean preOrdered,
ModelOrderBarycenterHeuristic.insertionSort(layer, barycenterStateComparator,
(ModelOrderBarycenterHeuristic) this);
} else {
// use comparator based on "<"
Collections.sort(layer, barycenterStateComparator);
}

Expand Down Expand Up @@ -193,6 +176,25 @@ protected void calculateBarycenters(final List<LNode> nodes, final boolean forwa
}
}

/**
* Constructs a Barycenter heuristic for crossing minimization.
*
* @param constraintResolver
* the constraint resolver
* @param random
* the random number generator
* @param portDistributor
* calculates the port ranks for the barycenter heuristic.
* @param graph
* current node order
*/
public BarycenterHeuristic(final ForsterConstraintResolver constraintResolver, final Random random,
final AbstractBarycenterPortDistributor portDistributor, final LNode[][] graph) {
this.constraintResolver = constraintResolver;
this.random = random;
this.portDistributor = portDistributor;
}

/** the amount of random value to add to each calculated barycenter. */
private static final float RANDOM_AMOUNT = 0.07f;

Expand All @@ -210,7 +212,7 @@ protected void calculateBarycenters(final List<LNode> nodes, final boolean forwa
* @return a pair containing the summed port positions of the connected ports as the first, and
* the number of connected edges as the second entry.
*/
private void calculateBarycenter(final LNode node, final boolean forward) {
private void calculateBarycenter(final LNode node, final boolean forward) {// javadoc for this method outdated

// Check if the node group's barycenter was already computed
if (stateOf(node).visited) {
Expand Down Expand Up @@ -240,7 +242,7 @@ private void calculateBarycenter(final LNode node, final boolean forward) {
// Update this node group's values
stateOf(node).degree += stateOf(fixedNode).degree;
stateOf(node).summedWeight += stateOf(fixedNode).summedWeight;
}
} // else { }
} else {
stateOf(node).summedWeight += portRanks[fixedPort.id];
stateOf(node).degree++;
Expand Down Expand Up @@ -351,10 +353,14 @@ public boolean minimizeCrossings(final LNode[][] order, final int freeLayerIndex

@Override
public boolean setFirstLayerOrder(final LNode[][] order, final boolean isForwardSweep) {
// if sweeping forward, startIndex = 0, else the last existing element of order
int startIndex = startIndex(isForwardSweep, order.length);
// extract first layer into List<LNode>
List<LNode> nodes = Lists.newArrayList(
order[startIndex]);
// randomize nodes' barycenters
minimizeCrossings(nodes, false, true, isForwardSweep);
// fill first layer with nodes
int index = 0;
for (LNode nodeGroup : nodes) {
order[startIndex][index++] = nodeGroup;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ public class GraphInfoHolder implements IInitializable {
private AllCrossingsCounter crossingsCounter;
private int nPorts;


/**
* Create object collecting information about a graph.
*
Expand All @@ -76,7 +75,7 @@ public class GraphInfoHolder implements IInitializable {
public GraphInfoHolder(final LGraph graph, final CrossMinType crossMinType, final List<GraphInfoHolder> graphs) {
lGraph = graph;
currentNodeOrder = graph.toNodeArray();

// Hierarchy information.
parent = lGraph.getParentNode();
hasParent = parent != null;
Expand All @@ -92,7 +91,7 @@ public GraphInfoHolder(final LGraph graph, final CrossMinType crossMinType, fina
layerSweepTypeDecider = new LayerSweepTypeDecider(this);
List<IInitializable> initializables =
Lists.newArrayList(this, crossingsCounter, layerSweepTypeDecider, portDistributor);

if (crossMinType == CrossMinType.BARYCENTER
&& !graph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_FORCE_NODE_MODEL_ORDER)) {
ForsterConstraintResolver constraintResolver = new ForsterConstraintResolver(currentNodeOrder);
Expand All @@ -105,6 +104,8 @@ public GraphInfoHolder(final LGraph graph, final CrossMinType crossMinType, fina
initializables.add(constraintResolver);
crossMinimizer = new ModelOrderBarycenterHeuristic(constraintResolver, random,
(AbstractBarycenterPortDistributor) portDistributor, currentNodeOrder);
} else if (crossMinType == CrossMinType.MEDIAN) {
crossMinimizer = new MedianHeuristic(random);
} else {
crossMinimizer = new GreedySwitchHeuristic(crossMinType, this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,9 @@ public enum CrossMinType {
/** Use one-sided GreedySwitchHeuristic. */
ONE_SIDED_GREEDY_SWITCH,
/** Use two-sided GreedySwitchHeuristic. */
TWO_SIDED_GREEDY_SWITCH
TWO_SIDED_GREEDY_SWITCH,
/** Use MedianHeuristic */
MEDIAN
}

/** intermediate processing configuration. */
Expand Down
Loading

0 comments on commit c071a93

Please sign in to comment.