All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cdc.graphs.core.GraphPartialOrder Maven / Gradle / Ivy

There is a newer version: 0.71.2
Show newest version
package cdc.graphs.core;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import cdc.graphs.EdgeDirection;
import cdc.graphs.GraphAdapter;
import cdc.graphs.PartialOrderPosition;
import cdc.util.lang.Checks;

/**
 * Utility related to graphs that define a partial order.
 * 

* This can also be applied to total orders. *

* WARNING: by convention, {@code X -> Y} means {@code X > Y}. * * @author Damien Carbonne * * @param Node class * @param Edge class */ public class GraphPartialOrder extends GraphBase { private final GraphCycles cycles; private final GraphTransitiveClosure closure; private static final int NONE = 0; private static final int ALL = 15; private static final EdgeDirection GREATER_DIR = EdgeDirection.INGOING; private static final EdgeDirection LESS_DIR = GREATER_DIR.opposite(); public GraphPartialOrder(GraphAdapter adapter) { super(adapter); this.cycles = new GraphCycles<>(adapter); this.closure = new GraphTransitiveClosure<>(adapter); } /** * @return {@code true} if the underlying graph defines a partial (or total) order. * */ public boolean isPartialOrTotalOrder() { return !cycles.containsCycles(); } /** * Returns the relative position of 2 nodes. *

* WARNING: partial order of the underlying graph is not checked. * * @param left The left node. * @param right The right node. * @return The position of {@code left} relatively to {@code right}. * @throws IllegalArgumentException When {@code left} or {@code right} don't belong to underlying graph. * */ public PartialOrderPosition compare(N left, N right) { Checks.isTrue(adapter.containsNode(left), "Unknown left node {}", left); Checks.isTrue(adapter.containsNode(right), "Unknown right node {}", right); // FIXME There must exist a better solution if (left.equals(right)) { return PartialOrderPosition.EQUAL; } else if (getAllGreaterOrEqualNodes(left).contains(right)) { return PartialOrderPosition.LESS_THAN; } else if (getAllLessOrEqualNodes(left).contains(right)) { return PartialOrderPosition.GREATER_THAN; } else { return PartialOrderPosition.UNRELATED; } } /** * Returns the nodes that are directly connected to, and greater than, a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @return The nodes that are directly connected to, and greater than, {@code node}. */ public Set getDirectGreaterThanNodes(N node) { return getAdapter().getConnectedNodes(node, GREATER_DIR); } /** * Returns the nodes that are directly connected to, and less than, a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @return The nodes that are directly connected to, and less than, {@code node}. */ public Set getDirectLessThanNodes(N node) { return getAdapter().getConnectedNodes(node, LESS_DIR); } /** * Returns the nodes that are greater than a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @return The nodes that are greater than {@code node}. */ public Set getAllGreaterThanNodes(N node) { final Set set = getAllGreaterOrEqualNodes(node); set.remove(node); return set; } /** * Returns the nodes that are less than a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @return The nodes that are less than {@code node}. */ public Set getAllLessThanNodes(N node) { final Set set = getAllLessOrEqualNodes(node); set.remove(node); return set; } /** * Returns the nodes that are greater than, or equal to, a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @return The nodes that are greater than, or equal to, {@code node}. */ public Set getAllGreaterOrEqualNodes(N node) { return closure.computeTransitiveClosureNodes(node, GREATER_DIR); } /** * Returns the nodes that are less than, or equal to, a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @return The nodes that are less than, or equal to, {@code node}. */ public Set getAllLessOrEqualNodes(N node) { return closure.computeTransitiveClosureNodes(node, LESS_DIR); } /** * Returns the nodes that are related (equal, less than or greater than) to a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @return The nodes that are related (equal, less than or greater than) to {@code node}. */ public Set getAllRelatedNodes(N node) { return closure.computeTransitiveClosureNodes(node, null); } /** * Returns the nodes that are not related to a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @return The nodes that are not related to {@code node}. */ public Set getAllUnrelatedNodes(N node) { final Set set = new HashSet<>(); for (final N n : getAdapter().getNodes()) { set.add(n); } set.remove(node); set.removeAll(getAllGreaterThanNodes(node)); set.removeAll(getAllLessThanNodes(node)); return set; } /** * Returns all the nodes that have a position relatively to a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @param position The relative position. * @return All the nodes that have this {@code position} relatively to {@code node}. */ public Set getAllNodes(N node, PartialOrderPosition position) { Checks.isNotNull(node, "node"); Checks.isNotNull(position, "position"); final Set set; if (position == PartialOrderPosition.EQUAL) { set = new HashSet<>(); set.add(node); } else if (position == PartialOrderPosition.GREATER_THAN) { set = getAllGreaterThanNodes(node); } else if (position == PartialOrderPosition.LESS_THAN) { set = getAllLessThanNodes(node); } else { set = getAllUnrelatedNodes(node); } return set; } private static int toMask(PartialOrderPosition... positions) { int mask = 0; for (final PartialOrderPosition position : positions) { if (position != null) { mask |= 1 << position.ordinal(); } } return mask; } private static boolean isSet(int mask, PartialOrderPosition position) { return (mask & (1 << position.ordinal())) != 0; } /** * Returns all the nodes that have one or many positions relatively to a node. *

* WARNING: partial order of the underlying graph is not checked. * * @param node The node. * @param positions The relative positions. * @return All the nodes that have a position among {@code positions} relatively to {@code node}. */ public Set getAllNodes(N node, PartialOrderPosition... positions) { final int mask = toMask(positions); if (mask == ALL) { final Set set = new HashSet<>(); for (final N n : getAdapter().getNodes()) { set.add(n); } return set; } else if (mask == NONE) { return Collections.emptySet(); } else { final Set set = new HashSet<>(); if (isSet(mask, PartialOrderPosition.UNRELATED)) { for (final N n : getAdapter().getNodes()) { set.add(n); } if (!isSet(mask, PartialOrderPosition.EQUAL)) { set.remove(node); } if (!isSet(mask, PartialOrderPosition.LESS_THAN)) { set.removeAll(getAllLessThanNodes(node)); } if (!isSet(mask, PartialOrderPosition.GREATER_THAN)) { set.removeAll(getAllGreaterThanNodes(node)); } } else { if (isSet(mask, PartialOrderPosition.EQUAL)) { set.add(node); } if (isSet(mask, PartialOrderPosition.LESS_THAN)) { set.addAll(getAllLessThanNodes(node)); } if (isSet(mask, PartialOrderPosition.GREATER_THAN)) { set.addAll(getAllGreaterThanNodes(node)); } } return set; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy