use of au.gov.asd.tac.constellation.utilities.datastructure.Tuple in project constellation by constellation-app.
the class TriangleUtilities method countTrianglesTriplets.
/*
* This method counts the number of triangles
* and the total number of triplets on the graph.
*/
public static Tuple<Float, Float> countTrianglesTriplets(final GraphReadMethods graph) {
final int vxCount = graph.getVertexCount();
final BitSet[] allNeighbours = new BitSet[vxCount];
final BitSet update = new BitSet(vxCount);
Float triangles = 0F;
Float triplets = 0F;
// initialise variables
for (int vxPosition = 0; vxPosition < vxCount; vxPosition++) {
allNeighbours[vxPosition] = new BitSet(vxCount);
// get the vertex ID at this position
final int vxId = graph.getVertex(vxPosition);
// collect neighbours
final BitSet neighbours = new BitSet(vxCount);
for (int neighbourPosition = 0; neighbourPosition < graph.getVertexNeighbourCount(vxId); neighbourPosition++) {
final int nxId = graph.getVertexNeighbour(vxId, neighbourPosition);
final int nxPosition = graph.getVertexPosition(nxId);
neighbours.set(nxPosition, true);
}
// not interested in neighbours to themselves
neighbours.set(vxPosition, false);
allNeighbours[vxPosition].or(neighbours);
update.set(vxPosition, true);
}
// checking for triangles
for (int one = update.nextSetBit(0); one >= 0; one = update.nextSetBit(one + 1)) {
for (int two = update.nextSetBit(one); two >= one; two = update.nextSetBit(two + 1)) {
// are these two vertices connected?
if (allNeighbours[one].get(two) && allNeighbours[two].get(one)) {
// determine common neighbours between them, each one is a triangle
final BitSet intersection = new BitSet(vxCount);
intersection.or(allNeighbours[one]);
intersection.and(allNeighbours[two]);
for (int three = intersection.nextSetBit(two); three >= two; three = intersection.nextSetBit(three + 1)) {
triangles += 1;
}
final BitSet union = new BitSet(vxCount);
union.or(allNeighbours[one]);
union.or(allNeighbours[two]);
union.set(one, false);
union.set(two, false);
for (int three = union.nextSetBit(two); three >= two; three = union.nextSetBit(three + 1)) {
triplets += 1;
}
}
}
}
return new Tuple<>(triangles, triplets);
}
use of au.gov.asd.tac.constellation.utilities.datastructure.Tuple in project constellation by constellation-app.
the class TriangleUtilities method getTriangles.
/*
This method counts the number of triangles each vertex is in
Returning a tuple where the first entry is a list of neighbours each node
is in a triangle with, and the second entry is count of the number of
triangles that node is in, and also the total number of triangles
*/
public static Tuple<Tuple<BitSet[], float[]>, Float> getTriangles(final GraphReadMethods graph) {
final int vxCount = graph.getVertexCount();
final BitSet[] allNeighbours = new BitSet[vxCount];
final float[] scores = new float[vxCount];
final BitSet update = new BitSet(vxCount);
final BitSet[] triangleNeighbours = new BitSet[vxCount];
float triangles = 0;
// initialise variables
for (int vxPosition = 0; vxPosition < vxCount; vxPosition++) {
allNeighbours[vxPosition] = new BitSet(vxCount);
triangleNeighbours[vxPosition] = new BitSet(vxCount);
scores[vxPosition] = 0;
// get the vertex ID at this position
final int vxId = graph.getVertex(vxPosition);
// collect neighbours
final BitSet neighbours = new BitSet(vxCount);
for (int neighbourPosition = 0; neighbourPosition < graph.getVertexNeighbourCount(vxId); neighbourPosition++) {
final int nxId = graph.getVertexNeighbour(vxId, neighbourPosition);
final int nxPosition = graph.getVertexPosition(nxId);
neighbours.set(nxPosition, true);
}
// not interested in neighbours to themselves
neighbours.set(vxPosition, false);
// if at least two neighbours, store them for triangle checking
if (neighbours.cardinality() > 1) {
allNeighbours[vxPosition].or(neighbours);
update.set(vxPosition, true);
}
}
// checking for triangles
for (int one = update.nextSetBit(0); one >= 0; one = update.nextSetBit(one + 1)) {
for (int two = update.nextSetBit(one); two >= one; two = update.nextSetBit(two + 1)) {
// are these two vertices connected?
if (allNeighbours[one].get(two) && allNeighbours[two].get(one)) {
// determine common neighbours between them, each one is a triangle
final BitSet intersection = new BitSet(vxCount);
intersection.or(allNeighbours[one]);
intersection.and(allNeighbours[two]);
for (int three = intersection.nextSetBit(two); three >= two; three = intersection.nextSetBit(three + 1)) {
scores[one] += 1;
scores[two] += 1;
scores[three] += 1;
triangleNeighbours[one].set(two, true);
triangleNeighbours[one].set(three, true);
triangleNeighbours[two].set(one, true);
triangleNeighbours[two].set(three, true);
triangleNeighbours[three].set(two, true);
triangleNeighbours[three].set(one, true);
triangles += 1;
}
}
}
}
return new Tuple<>(new Tuple<>(triangleNeighbours, scores), triangles);
}
use of au.gov.asd.tac.constellation.utilities.datastructure.Tuple in project constellation by constellation-app.
the class AbstractPathsLayer method update.
@Override
public PImage update() {
if (graph == null) {
return null;
}
final Set<Marker> onScreenMarkers;
final List<Tuple<GraphElement, GraphElement>> paths = new ArrayList<>();
try (final ReadableGraph readableGraph = graph.getReadableGraph()) {
// update on screen markers, collecting the ids of the vertices involved in valid paths along the way
final ScreenPosition topLeft = map.getScreenPosition(map.getTopLeftBorder());
final ScreenPosition bottomRight = map.getScreenPosition(map.getBottomRightBorder());
onScreenMarkers = renderer.getMarkerCache().keys().stream().filter(marker -> {
final ScreenPosition markerPosition = map.getScreenPosition(marker.getLocation());
final boolean onScreen = markerPosition != null && markerPosition.x > topLeft.x && markerPosition.y > topLeft.y && markerPosition.x < bottomRight.x && markerPosition.y < bottomRight.y;
if (drawPathsToOffscreenMarkers() || onScreen) {
final Set<GraphElement> elementsAtMarker = renderer.getMarkerCache().get(marker);
if (elementsAtMarker != null) {
elementsAtMarker.forEach(element -> paths.addAll(getPathsForElement(readableGraph, element)));
}
}
return onScreen;
}).collect(Collectors.toSet());
onScreenMarkerCount = onScreenMarkers.size();
}
if (onScreenMarkers.isEmpty()) {
return null;
}
final Map<GraphElement, Marker> elementToMarkerCache = new HashMap<>();
renderer.getMarkerCache().keys().forEach(marker -> renderer.getMarkerCache().get(marker).forEach(element -> elementToMarkerCache.put(element, marker)));
// set up a color palette
final int[] palette = Arrays.asList(ConstellationColor.createLinearPalette(N_COLORS, SRC_COLOR, DST_COLOR)).stream().mapToInt(c -> MarkerUtilities.color(c)).toArray();
final int width = renderer.width - 5;
final int height = renderer.height - 5;
final PGraphics pathsImage = renderer.createGraphics(width, height, PConstants.JAVA2D);
pathsImage.beginDraw();
// deduplicate paths, storing duplicate counts
int maxWeight = 1;
final Map<Tuple<GraphElement, GraphElement>, Integer> dedupedPaths = new HashMap<>();
for (final Tuple<GraphElement, GraphElement> path : paths) {
if (dedupedPaths.containsKey(path)) {
final int weight = dedupedPaths.get(path) + 1;
if (weight > maxWeight) {
maxWeight = weight;
}
dedupedPaths.put(path, weight);
} else {
dedupedPaths.put(path, 1);
}
}
// draw weighted paths
final int maxWeightFinal = maxWeight;
dedupedPaths.forEach((path, weight) -> {
final Marker sourceMarker = elementToMarkerCache.get(path.getFirst());
final Marker destinationMarker = elementToMarkerCache.get(path.getSecond());
final boolean validPath = (drawPathsToOffscreenMarkers() && (onScreenMarkers.contains(sourceMarker) || onScreenMarkers.contains(destinationMarker))) || (onScreenMarkers.contains(sourceMarker) && onScreenMarkers.contains(destinationMarker));
if (validPath) {
final Location sourceLocation = sourceMarker != null ? sourceMarker.getLocation() : null;
final Location destinationLocation = destinationMarker != null ? destinationMarker.getLocation() : null;
if (sourceLocation != null && destinationLocation != null) {
final ScreenPosition sourcePosition = map.getScreenPosition(sourceLocation);
final ScreenPosition destinationPosition = map.getScreenPosition(destinationLocation);
final float lineWidth = Math.max(maxWeightFinal > MAX_LINE_WIDTH ? (MAX_LINE_WIDTH * (weight / (float) maxWeightFinal)) + 1 : weight + 1, 2);
pathsImage.strokeWeight(lineWidth);
pathsImage.pushMatrix();
pathsImage.translate(sourcePosition.x, sourcePosition.y);
pathsImage.rotate(PApplet.atan2((destinationPosition.y - sourcePosition.y), (destinationPosition.x - sourcePosition.x)));
final float translatedDestiniationPosition = (float) Math.hypot(destinationPosition.x - sourcePosition.x, destinationPosition.y - sourcePosition.y);
drawColoredLine(pathsImage, translatedDestiniationPosition, lineWidth, palette);
pathsImage.popMatrix();
}
}
});
pathsImage.endDraw();
return pathsImage;
}
use of au.gov.asd.tac.constellation.utilities.datastructure.Tuple in project constellation by constellation-app.
the class EntityPathsLayer method getPathsForElement.
@Override
public List<Tuple<GraphElement, GraphElement>> getPathsForElement(final ReadableGraph graph, final GraphElement element) {
final List<Tuple<GraphElement, GraphElement>> paths = new ArrayList<>();
if (element.getType() == GraphElementType.VERTEX) {
final int vertexTypeAttributeId = AnalyticConcept.VertexAttribute.TYPE.get(graph);
final int transactionDateTimeAttributeId = TemporalConcept.TransactionAttribute.DATETIME.get(graph);
final SchemaVertexType vertexType = graph.getObjectValue(vertexTypeAttributeId, element.getId());
if (vertexType != null && vertexType.isSubTypeOf(AnalyticConcept.VertexType.LOCATION)) {
final int neighbourCount = graph.getVertexNeighbourCount(element.getId());
for (int neighbourPosition = 0; neighbourPosition < neighbourCount; neighbourPosition++) {
final int neighbourId = graph.getVertexNeighbour(element.getId(), neighbourPosition);
final SchemaVertexType neighbourType = graph.getObjectValue(vertexTypeAttributeId, neighbourId);
if (neighbourType != null && !neighbourType.isSubTypeOf(AnalyticConcept.VertexType.LOCATION)) {
final Set<Long> locationDateTimes = new HashSet<>();
final int neighbourLinkId = graph.getLink(element.getId(), neighbourId);
final int neighbourLinkTransactionCount = graph.getLinkTransactionCount(neighbourLinkId);
for (int neighbourLinkTransactionPosition = 0; neighbourLinkTransactionPosition < neighbourLinkTransactionCount; neighbourLinkTransactionPosition++) {
final int neighbourLinkTransactionId = graph.getLinkTransaction(neighbourLinkId, neighbourLinkTransactionPosition);
final long neighbourLinkTransactionDateTime = graph.getLongValue(transactionDateTimeAttributeId, neighbourLinkTransactionId);
locationDateTimes.add(neighbourLinkTransactionDateTime);
}
final List<Integer> validNeighbourNeighbours = new ArrayList<>();
final int neighbourNeighbourCount = graph.getVertexNeighbourCount(neighbourId);
for (int neighbourNeighbourPosition = 0; neighbourNeighbourPosition < neighbourNeighbourCount; neighbourNeighbourPosition++) {
final int neighbourNeighbourId = graph.getVertexNeighbour(neighbourId, neighbourNeighbourPosition);
final SchemaVertexType neighbourNeighbourType = graph.getObjectValue(vertexTypeAttributeId, neighbourNeighbourId);
if (neighbourNeighbourType != null && neighbourNeighbourType.isSubTypeOf(AnalyticConcept.VertexType.LOCATION)) {
validNeighbourNeighbours.add(neighbourNeighbourId);
}
}
locationDateTimes.forEach(locationDateTime -> {
int pathNeighbourNeighbour = GraphConstants.NOT_FOUND;
long closestTimeDifference = Long.MAX_VALUE;
for (final int neighbourNeighbourId : validNeighbourNeighbours) {
final int neighbourNeighbourLinkId = graph.getLink(neighbourId, neighbourNeighbourId);
final int neighbourNeighbourLinkTransactionCount = graph.getLinkTransactionCount(neighbourNeighbourLinkId);
for (int neighbourNeighbourLinkTransactionPosition = 0; neighbourNeighbourLinkTransactionPosition < neighbourNeighbourLinkTransactionCount; neighbourNeighbourLinkTransactionPosition++) {
final int neighbourNeighbourLinkTransactionId = graph.getLinkTransaction(neighbourNeighbourLinkId, neighbourNeighbourLinkTransactionPosition);
final long neighbourNeighbourLinkTransactionDateTime = graph.getLongValue(transactionDateTimeAttributeId, neighbourNeighbourLinkTransactionId);
final long timeDifference = neighbourNeighbourLinkTransactionDateTime - locationDateTime;
if (timeDifference > 0 && timeDifference < closestTimeDifference) {
closestTimeDifference = timeDifference;
pathNeighbourNeighbour = neighbourNeighbourId;
}
}
}
if (pathNeighbourNeighbour != GraphConstants.NOT_FOUND) {
paths.add(Tuple.create(element, new GraphElement(pathNeighbourNeighbour, GraphElementType.VERTEX)));
}
});
}
}
}
}
return paths;
}
use of au.gov.asd.tac.constellation.utilities.datastructure.Tuple in project constellation by constellation-app.
the class LocationPathsLayer method getPathsForElement.
@Override
public List<Tuple<GraphElement, GraphElement>> getPathsForElement(final ReadableGraph graph, final GraphElement element) {
final List<Tuple<GraphElement, GraphElement>> paths = new ArrayList<>();
if (element.getType() == GraphElementType.VERTEX) {
final int vertexTypeAttributeId = AnalyticConcept.VertexAttribute.TYPE.get(graph);
final SchemaVertexType vertexType = graph.getObjectValue(vertexTypeAttributeId, element.getId());
if (vertexType != null && vertexType.isSubTypeOf(AnalyticConcept.VertexType.LOCATION)) {
final int neighbourCount = graph.getVertexNeighbourCount(element.getId());
for (int neighbourPosition = 0; neighbourPosition < neighbourCount; neighbourPosition++) {
final int neighbourId = graph.getVertexNeighbour(element.getId(), neighbourPosition);
final SchemaVertexType neighbourType = graph.getObjectValue(vertexTypeAttributeId, neighbourId);
if (neighbourType != null && neighbourType.isSubTypeOf(AnalyticConcept.VertexType.LOCATION)) {
final int neighbourLinkId = graph.getLink(element.getId(), neighbourId);
final int outgoingDirection = element.getId() < neighbourId ? GraphConstants.UPHILL : GraphConstants.DOWNHILL;
final int linkOutgoingTransactionCount = graph.getLinkTransactionCount(neighbourLinkId, outgoingDirection);
for (int i = 0; i < linkOutgoingTransactionCount; i++) {
paths.add(Tuple.create(element, new GraphElement(neighbourId, GraphElementType.VERTEX)));
}
}
}
}
}
return paths;
}
Aggregations