/* * This file is part of the Trickl Open Source Libraries. * * Trickl Open Source Libraries - http://open.trickl.com/ * * Copyright (C) 2011 Tim Gee. * * Trickl Open Source Libraries are free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Trickl Open Source Libraries are distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this project. If not, see <http://www.gnu.org/licenses/>. */ package com.trickl.graph; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.TreeSet; import org.jgrapht.Graph; import org.jgrapht.UndirectedGraph; public final class Graphs { private Graphs() { } static public <V, E> boolean isEdgeDirected(Graph<V, E> graph, E edge) { V source = graph.getEdgeSource(edge); V target = graph.getEdgeTarget(edge); E oppositeEdge = graph.getEdge(target, source); return !oppositeEdge.equals(edge); } static public <V1, E1, V2, E2> Map<V1, V2> aggregate(Graph<V1, E1> source, Graph<V2, E2> target, Map<V1, Integer> aggregateGroups, CopyVertexFactory<V2, V1> vertexFactory, CopyEdgeFactory<V2, E2, E1> edgeFactory) { CopyGraphVisitor<V1, E1, V2, E2> copyGraphVisitor = new CopyGraphVisitor( source, target, vertexFactory, edgeFactory); copyGraphVisitor.setAggregationGroups(aggregateGroups); DepthFirstSearch<V1, E1> depthFirstTraversal = new DepthFirstSearch<V1, E1>(source); depthFirstTraversal.traverse(copyGraphVisitor); return copyGraphVisitor.getVertexMap(); } static public <V1, E1, V2, E2> Map<V1, V2> aggregate(Graph<V1, E1> source, Graph<V2, E2> target, Map<V1, Integer> aggregateGroups) { return aggregate(source, target, aggregateGroups, null, null); } static public <V1, E1, V2, E2> Map<V1, V2> copy(Graph<V1, E1> source, Graph<V2, E2> target, CopyVertexFactory<V2, V1> vertexFactory, CopyEdgeFactory<V2, E2, E1> edgeFactory) { return aggregate(source, target, null, vertexFactory, edgeFactory); } public static <V, E> Map<V, Double> getNeighbourhoodWeights(UndirectedGraph<V, E> graph, V vertex, NeighbourhoodFunction neighbourhoodFunction, double weightThreshold) { final Map<V, Double> distances = new HashMap<V, Double>(); Map<V, Double> weights = new HashMap<V, Double>(); // Use Dijkstra's algorithm to calculate distances from this vertex TreeSet<V> queue = new TreeSet<V>(new Comparator<V>() { @Override public int compare(V lhs, V rhs) { int result = 0; Double lhsDistance = distances.get(lhs); Double rhsDistance = distances.get(rhs); if (lhsDistance != null && rhsDistance != null) { result = lhsDistance.compareTo(rhsDistance); } return result; } }); distances.put(vertex, 0.0); weights.put(vertex, neighbourhoodFunction.evaluate(0.)); queue.add(vertex); while (!queue.isEmpty()) { V u = queue.first(); queue.remove(u); for (E edge : graph.edgesOf(u)) { V v = org.jgrapht.Graphs.getOppositeVertex(graph, edge, u); double altDistance = distances.get(u) + graph.getEdgeWeight(graph.getEdge(u, v)); double altWeight = neighbourhoodFunction.evaluate(altDistance); // Only consider vertices within a distance that gives a sufficient weight if (altWeight > weightThreshold) { if (!distances.containsKey(v) || altDistance < distances.get(v)) { queue.remove(v); distances.put(v, altDistance); weights.put(v, altWeight); queue.add(v); } } } } return weights; } }