Search in sources :

Example 1 with GreedySwitchType

use of org.eclipse.elk.alg.layered.options.GreedySwitchType in project elk by eclipse.

the class ElkLayered method reviewAndCorrectHierarchicalProcessors.

/**
 * It is not permitted that any of the child-graphs specifies a hierarchical
 * layout processor ({@link IHierarchyAwareLayoutProcessor}) that is not specified by the root node.
 *
 * It depends on the concrete processor how this is fixed.
 *
 * @param root the root graph
 * @param graphs all graphs of the handled hierarchy
 */
private void reviewAndCorrectHierarchicalProcessors(final LGraph root, final Collection<LGraph> graphs) {
    // Crossing minimization
    // overwrite invalid child configuration (only layer sweep is hierarchical)
    CrossingMinimizationStrategy parentCms = root.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY);
    if (parentCms != CrossingMinimizationStrategy.LAYER_SWEEP) {
        graphs.forEach(child -> {
            CrossingMinimizationStrategy childCms = child.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY);
            if (childCms == CrossingMinimizationStrategy.LAYER_SWEEP) {
                throw new UnsupportedGraphException("The hierarchy aware processor " + childCms + " in child node " + child + " is only allowed if the root node specifies the same hierarchical processor.");
            }
        });
    }
    // Greedy switch (simply copy the behavior of the root to all children)
    final GreedySwitchType rootType = root.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE);
    graphs.forEach(g -> g.setProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE, rootType));
}
Also used : UnsupportedGraphException(org.eclipse.elk.core.UnsupportedGraphException) CrossingMinimizationStrategy(org.eclipse.elk.alg.layered.options.CrossingMinimizationStrategy) GreedySwitchType(org.eclipse.elk.alg.layered.options.GreedySwitchType)

Example 2 with GreedySwitchType

use of org.eclipse.elk.alg.layered.options.GreedySwitchType in project elk by eclipse.

the class GraphConfigurator method getPhaseIndependentLayoutProcessorConfiguration.

/**
 * Returns an intermediate processing configuration with processors not tied to specific phases.
 *
 * @param lgraph the layered graph to be processed. The configuration may vary depending on certain
 *               properties of the graph.
 * @return intermediate processing configuration. May be {@code null}.
 */
private LayoutProcessorConfiguration<LayeredPhases, LGraph> getPhaseIndependentLayoutProcessorConfiguration(final LGraph lgraph) {
    Set<GraphProperties> graphProperties = lgraph.getProperty(InternalProperties.GRAPH_PROPERTIES);
    // Basic configuration
    LayoutProcessorConfiguration<LayeredPhases, LGraph> configuration = LayoutProcessorConfiguration.createFrom(BASELINE_PROCESSING_CONFIGURATION);
    // Hierarchical layout.
    // Note that the recursive graph layout engine made sure that at this point
    // 'INCLUDE_CHILDREN' has been propagated to all parent nodes with 'INHERIT'.
    // Thus, every lgraph of the hierarchical lgraph structure is configured with the following additions.
    HierarchyHandling hierarchyHandling = lgraph.getProperty(LayeredOptions.HIERARCHY_HANDLING);
    if (hierarchyHandling == HierarchyHandling.INCLUDE_CHILDREN) {
        configuration.addAll(HIERARCHICAL_ADDITIONS);
    }
    // Port side processor, put to first slot only if requested and routing is orthogonal
    if (lgraph.getProperty(LayeredOptions.FEEDBACK_EDGES)) {
        configuration.addBefore(LayeredPhases.P1_CYCLE_BREAKING, IntermediateProcessorStrategy.PORT_SIDE_PROCESSOR);
    } else {
        configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.PORT_SIDE_PROCESSOR);
    }
    // If the graph has a label manager, so add label management additions
    if (lgraph.getProperty(LabelManagementOptions.LABEL_MANAGER) != null) {
        configuration.addAll(LABEL_MANAGEMENT_ADDITIONS);
    }
    // If the graph should be laid out interactively, add the layers and positions to the nodes.
    if (lgraph.getProperty(LayeredOptions.INTERACTIVE_LAYOUT)) {
        configuration.addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.CONSTRAINTS_POSTPROCESSOR);
    }
    // graph transformations for unusual layout directions
    switch(lgraph.getProperty(LayeredOptions.DIRECTION)) {
        case LEFT:
        case DOWN:
        case UP:
            configuration.addBefore(LayeredPhases.P1_CYCLE_BREAKING, IntermediateProcessorStrategy.DIRECTION_PREPROCESSOR).addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.DIRECTION_POSTPROCESSOR);
            break;
        default:
            // don't need any processors here
            break;
    }
    // Additional dependencies
    if (graphProperties.contains(GraphProperties.COMMENTS)) {
        configuration.addBefore(LayeredPhases.P1_CYCLE_BREAKING, IntermediateProcessorStrategy.COMMENT_PREPROCESSOR).addBefore(LayeredPhases.P4_NODE_PLACEMENT, IntermediateProcessorStrategy.COMMENT_NODE_MARGIN_CALCULATOR).addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.COMMENT_POSTPROCESSOR);
    }
    // Node-Promotion application for reduction of dummy nodes after layering
    if (lgraph.getProperty(LayeredOptions.LAYERING_NODE_PROMOTION_STRATEGY) != NodePromotionStrategy.NONE) {
        configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.NODE_PROMOTION);
    }
    // Preserve certain partitions during layering
    if (graphProperties.contains(GraphProperties.PARTITIONS)) {
        configuration.addBefore(LayeredPhases.P1_CYCLE_BREAKING, IntermediateProcessorStrategy.PARTITION_PREPROCESSOR);
        configuration.addBefore(LayeredPhases.P2_LAYERING, IntermediateProcessorStrategy.PARTITION_MIDPROCESSOR);
        configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.PARTITION_POSTPROCESSOR);
    }
    // Additional horizontal compaction depends on orthogonal edge routing
    if (lgraph.getProperty(LayeredOptions.COMPACTION_POST_COMPACTION_STRATEGY) != GraphCompactionStrategy.NONE && lgraph.getProperty(LayeredOptions.EDGE_ROUTING) != EdgeRouting.POLYLINE) {
        configuration.addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.HORIZONTAL_COMPACTOR);
    }
    // Move trees of high degree nodes to separate layers
    if (lgraph.getProperty(LayeredOptions.HIGH_DEGREE_NODES_TREATMENT)) {
        configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.HIGH_DEGREE_NODE_LAYER_PROCESSOR);
    }
    // Introduce in-layer constraints to preserve the order of regular nodes
    if (lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_SEMI_INTERACTIVE)) {
        configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.SEMI_INTERACTIVE_CROSSMIN_PROCESSOR);
    }
    // ElkLayered#reviewAndCorrectHierarchicalProcessors(...)
    if (activateGreedySwitchFor(lgraph)) {
        final GreedySwitchType greedySwitchType;
        if (isHierarchicalLayout(lgraph)) {
            greedySwitchType = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE);
        } else {
            greedySwitchType = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_TYPE);
        }
        IntermediateProcessorStrategy internalGreedyType = (greedySwitchType == GreedySwitchType.ONE_SIDED) ? IntermediateProcessorStrategy.ONE_SIDED_GREEDY_SWITCH : IntermediateProcessorStrategy.TWO_SIDED_GREEDY_SWITCH;
        configuration.addBefore(LayeredPhases.P4_NODE_PLACEMENT, internalGreedyType);
    }
    // Wrapping of graphs
    switch(lgraph.getProperty(LayeredOptions.WRAPPING_STRATEGY)) {
        case SINGLE_EDGE:
            configuration.addBefore(LayeredPhases.P4_NODE_PLACEMENT, IntermediateProcessorStrategy.SINGLE_EDGE_GRAPH_WRAPPER);
            break;
        case MULTI_EDGE:
            configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.BREAKING_POINT_INSERTER).addBefore(LayeredPhases.P4_NODE_PLACEMENT, IntermediateProcessorStrategy.BREAKING_POINT_PROCESSOR).addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.BREAKING_POINT_REMOVER);
            break;
        // OFF
        default:
    }
    if (lgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_STRATEGY) != OrderingStrategy.NONE) {
        configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.SORT_BY_INPUT_ORDER_OF_MODEL);
    }
    return configuration;
}
Also used : HierarchyHandling(org.eclipse.elk.core.options.HierarchyHandling) GraphProperties(org.eclipse.elk.alg.layered.options.GraphProperties) GreedySwitchType(org.eclipse.elk.alg.layered.options.GreedySwitchType) IntermediateProcessorStrategy(org.eclipse.elk.alg.layered.intermediate.IntermediateProcessorStrategy) LGraph(org.eclipse.elk.alg.layered.graph.LGraph)

Example 3 with GreedySwitchType

use of org.eclipse.elk.alg.layered.options.GreedySwitchType in project elk by eclipse.

the class GraphConfigurator method activateGreedySwitchFor.

/**
 * Greedy switch may be activated if the following holds.
 *
 * <h3>Hierarchical layout</h3>
 * <ol>
 *  <li>the {@link LayeredOptions#CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE} is set to something
 *      different than OFF</li>
 * </ol>
 *
 * <h3>Non-hierarchical layout</h3>
 * <ol>
 *  <li>no interactive crossing minimization is performed</li>
 *  <li>the {@link LayeredOptions#CROSSING_MINIMIZATION_GREEDY_SWITCH_TYPE} option is set to something different
 *      than OFF</li>
 *  <li>the activationThreshold is larger than or equal to the graph's number of nodes (or '0')</li>
 * </ol>
 * @return {@code true} if above condition holds, {@code false} otherwise.
 */
public static boolean activateGreedySwitchFor(final LGraph lgraph) {
    // First, check the hierarchical case
    if (isHierarchicalLayout(lgraph)) {
        // (and thus doesn't have to be checked here).
        return lgraph.getParentNode() == null && lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE) != GreedySwitchType.OFF;
    }
    // Second, if not hierarchical, check the slightly more complex non-hierarchical case
    GreedySwitchType greedySwitchType = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_TYPE);
    boolean interactiveCrossMin = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_SEMI_INTERACTIVE) || lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY) == CrossingMinimizationStrategy.INTERACTIVE;
    int activationThreshold = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_ACTIVATION_THRESHOLD);
    int graphSize = lgraph.getLayerlessNodes().size();
    return !interactiveCrossMin && greedySwitchType != GreedySwitchType.OFF && (activationThreshold == 0 || activationThreshold > graphSize);
}
Also used : GreedySwitchType(org.eclipse.elk.alg.layered.options.GreedySwitchType)

Aggregations

GreedySwitchType (org.eclipse.elk.alg.layered.options.GreedySwitchType)3 LGraph (org.eclipse.elk.alg.layered.graph.LGraph)1 IntermediateProcessorStrategy (org.eclipse.elk.alg.layered.intermediate.IntermediateProcessorStrategy)1 CrossingMinimizationStrategy (org.eclipse.elk.alg.layered.options.CrossingMinimizationStrategy)1 GraphProperties (org.eclipse.elk.alg.layered.options.GraphProperties)1 UnsupportedGraphException (org.eclipse.elk.core.UnsupportedGraphException)1 HierarchyHandling (org.eclipse.elk.core.options.HierarchyHandling)1