private void init(Graph<V, E> g, Set<V> vertexSet, Set<E> edgeSet) {
    // create a map between vertex value to its order(1st,2nd,etc)
    // "CAT"=1 "DOG"=2 "RHINO"=3

    this.mapVertexToOrder = new HashMap<V, Integer>(vertexSet.size());

    int counter = 0;
    for (V vertex : vertexSet) {
      mapVertexToOrder.put(vertex, new Integer(counter));
      counter++;
    }

    // create a friendlier representation of an edge
    // by order, like 2nd->3rd instead of B->A
    // use the map to convert vertex to order
    // on directed graph, edge A->B must be (A,B)
    // on undirected graph, edge A-B can be (A,B) or (B,A)

    this.labelsEdgesSet = new HashSet<LabelsEdge>(edgeSet.size());
    for (E edge : edgeSet) {
      V sourceVertex = g.getEdgeSource(edge);
      Integer sourceOrder = mapVertexToOrder.get(sourceVertex);
      int sourceLabel = sourceOrder.intValue();
      int targetLabel = (mapVertexToOrder.get(g.getEdgeTarget(edge))).intValue();

      LabelsEdge lablesEdge = new LabelsEdge(sourceLabel, targetLabel);
      this.labelsEdgesSet.add(lablesEdge);

      if (g instanceof UndirectedGraph<?, ?>) {
        LabelsEdge oppositeEdge = new LabelsEdge(targetLabel, sourceLabel);
        this.labelsEdgesSet.add(oppositeEdge);
      }
    }
  }
示例#2
0
  /** @see Graph#getEdgeWeight */
  @Override
  public double getEdgeWeight(E e) {
    double weight;

    // Always return the value from the weight map first and
    // only pass the call through as a backup
    if (weightMap.containsKey(e)) {
      weight = weightMap.get(e);
    } else {
      weight = super.getEdgeWeight(e);
    }

    return weight;
  }
示例#3
0
  /**
   * @param graph the graph to be ordered
   * @param orderByDegree should the vertices be ordered by their degree. This speeds up the VF2
   *     algorithm.
   * @param cacheEdges if true, the class creates a adjacency matrix and two arrays for incoming and
   *     outgoing edges for fast access.
   */
  public GraphOrdering(Graph<V, E> graph, boolean orderByDegree, boolean cacheEdges) {
    this.graph = graph;
    this.cacheEdges = cacheEdges;

    List<V> vertexSet = new ArrayList<>(graph.vertexSet());
    if (orderByDegree) {
      java.util.Collections.sort(vertexSet, new GeneralVertexDegreeComparator<>(graph));
    }

    vertexCount = vertexSet.size();
    mapVertexToOrder = new HashMap<>();
    mapOrderToVertex = new ArrayList<>(vertexCount);

    if (cacheEdges) {
      outgoingEdges = new int[vertexCount][];
      incomingEdges = new int[vertexCount][];
      adjMatrix = new Boolean[vertexCount][vertexCount];
    }

    Integer i = 0;
    for (V vertex : vertexSet) {
      mapVertexToOrder.put(vertex, i++);
      mapOrderToVertex.add(vertex);
    }
  }
  /** @see Graph#addEdge(Object, Object) */
  public E addEdge(V sourceVertex, V targetVertex) {
    assertVertexExist(sourceVertex);
    assertVertexExist(targetVertex);

    if (!allowingMultipleEdges && containsEdge(sourceVertex, targetVertex)) {
      return null;
    }

    if (!allowingLoops && sourceVertex.equals(targetVertex)) {
      throw new IllegalArgumentException(LOOPS_NOT_ALLOWED);
    }

    E e = edgeFactory.createEdge(sourceVertex, targetVertex);

    if (containsEdge(e)) { // this restriction should stay!

      return null;
    } else {
      IntrusiveEdge intrusiveEdge = createIntrusiveEdge(e, sourceVertex, targetVertex);

      edgeMap.put(e, intrusiveEdge);
      specifics.addEdgeToTouchingVertices(e);

      return e;
    }
  }
  /** @see Graph#addEdge(Object, Object, Object) */
  public boolean addEdge(V sourceVertex, V targetVertex, E e) {
    if (e == null) {
      throw new NullPointerException();
    } else if (containsEdge(e)) {
      return false;
    }

    assertVertexExist(sourceVertex);
    assertVertexExist(targetVertex);

    if (!allowingMultipleEdges && containsEdge(sourceVertex, targetVertex)) {
      return false;
    }

    if (!allowingLoops && sourceVertex.equals(targetVertex)) {
      throw new IllegalArgumentException(LOOPS_NOT_ALLOWED);
    }

    IntrusiveEdge intrusiveEdge = createIntrusiveEdge(e, sourceVertex, targetVertex);

    edgeMap.put(e, intrusiveEdge);
    specifics.addEdgeToTouchingVertices(e);

    return true;
  }
  /** @see Graph#edgeSet() */
  public Set<E> edgeSet() {
    if (unmodifiableEdgeSet == null) {
      unmodifiableEdgeSet = Collections.unmodifiableSet(edgeMap.keySet());
    }

    return unmodifiableEdgeSet;
  }
示例#7
0
  /**
   * @param vertexNumber the number which identifies the vertex v in this order.
   * @return the identifying numbers of all vertices which are connected to v by an edge incoming to
   *     v.
   */
  public int[] getInEdges(int vertexNumber) {
    if (cacheEdges && (incomingEdges[vertexNumber] != null)) {
      return incomingEdges[vertexNumber];
    }

    V v = getVertex(vertexNumber);
    Set<E> edgeSet;

    if (graph instanceof DirectedGraph<?, ?>) {
      edgeSet = ((DirectedGraph<V, E>) graph).incomingEdgesOf(v);
    } else {
      edgeSet = graph.edgesOf(v);
    }

    int[] vertexArray = new int[edgeSet.size()];
    int i = 0;

    for (E edge : edgeSet) {
      V source = graph.getEdgeSource(edge), target = graph.getEdgeTarget(edge);
      vertexArray[i++] = mapVertexToOrder.get(source.equals(v) ? target : source);
    }

    if (cacheEdges) {
      incomingEdges[vertexNumber] = vertexArray;
    }

    return vertexArray;
  }
  public void union(AbstractBaseGraph<V, E> g2) {
    if (!(this instanceof DirectedGraph<?, ?> && g2 instanceof DirectedGraph<?, ?>)) {
      return;
    }
    Set<V> vertexSet = g2.vertexSet();
    for (V vertex : vertexSet) {
      if (!containsVertex(vertex)) addVertex(vertex);
    }

    for (V vertex : vertexSet) {
      Set<E> edgeSet = g2.specifics.outgoingEdgesOf(vertex);
      for (E edge : edgeSet) {
        V sourceVertex = getEdgeSource(edge);
        V targetVertex = getEdgeTarget(edge);
        if (!allowingMultipleEdges && containsEdge(sourceVertex, targetVertex)) {
          continue;
        }

        if (!allowingLoops && sourceVertex.equals(targetVertex)) {
          continue;
        }

        if (containsEdge(edge)) {
          continue;
        } else {
          IntrusiveEdge intrusiveEdge = createIntrusiveEdge(edge, sourceVertex, targetVertex);

          edgeMap.put(edge, intrusiveEdge);
          specifics.addEdgeToTouchingVertices(edge);
        }
      }
    }
  }
 private void markPath(V v, V child, V stem, Set<V> blossom) {
   while (!contracted.get(v).equals(stem)) {
     blossom.add(contracted.get(v));
     blossom.add(contracted.get(match.get(v)));
     path.put(v, child);
     child = match.get(v);
     v = path.get(match.get(v));
   }
 }
示例#10
0
  public int[] getEdgeNumbers(E e) {
    V v1 = graph.getEdgeSource(e), v2 = graph.getEdgeTarget(e);

    int[] edge = new int[2];
    edge[0] = mapVertexToOrder.get(v1);
    edge[1] = mapVertexToOrder.get(v2);

    return edge;
  }
示例#11
0
  /** @see Graph#removeEdge(Object, Object) */
  public E removeEdge(V sourceVertex, V targetVertex) {
    E e = getEdge(sourceVertex, targetVertex);

    if (e != null) {
      specifics.removeEdgeFromTouchingVertices(e);
      edgeMap.remove(e);
    }

    return e;
  }
示例#12
0
  /** @see Graph#removeEdge(Object) */
  public boolean removeEdge(E e) {
    if (containsEdge(e)) {
      specifics.removeEdgeFromTouchingVertices(e);
      edgeMap.remove(e);

      return true;
    } else {
      return false;
    }
  }
示例#13
0
  /** @see WeightedGraph#setEdgeWeight */
  @Override
  public void setEdgeWeight(E e, double weight) {
    if (isWeightedGraph) {
      super.setEdgeWeight(e, weight);
    }

    // Always modify the weight map.  It would be a terrible violation
    // of the use contract to silently ignore changes to the weights.
    weightMap.put(e, weight);
  }
 /**
  * Get the vertex with the maximal label.
  *
  * @param vertexLabels Map that gives a label for each vertex.
  * @return Vertex with the maximal label.
  */
 private V getMaxLabelVertex(Map<V, Integer> vertexLabels) {
   Iterator<Entry<V, Integer>> iterator = vertexLabels.entrySet().iterator();
   Entry<V, Integer> max = iterator.next();
   while (iterator.hasNext()) {
     Entry<V, Integer> e = iterator.next();
     if (e.getValue() > max.getValue()) {
       max = e;
     }
   }
   return max.getKey();
 }
  /** {@inheritDoc} */
  public void generateGraph(
      Graph<V, E> target, VertexFactory<V> vertexFactory, Map<String, V> resultMap) {
    V lastVertex = null;

    for (int i = 0; i < size; ++i) {
      V newVertex = vertexFactory.createVertex();
      target.addVertex(newVertex);

      if (lastVertex == null) {
        if (resultMap != null) {
          resultMap.put(START_VERTEX, newVertex);
        }
      } else {
        target.addEdge(lastVertex, newVertex);
      }

      lastVertex = newVertex;
    }

    if ((resultMap != null) && (lastVertex != null)) {
      resultMap.put(END_VERTEX, lastVertex);
    }
  }
 private V lowestCommonAncestor(V a, V b) {
   Set<V> seen = new HashSet<>();
   for (; ; ) {
     a = contracted.get(a);
     seen.add(a);
     if (!match.containsKey(a)) {
       break;
     }
     a = path.get(match.get(a));
   }
   for (; ; ) {
     b = contracted.get(b);
     if (seen.contains(b)) {
       return b;
     }
     b = path.get(match.get(b));
   }
 }
示例#17
0
  /** {@inheritDoc} */
  public void generateGraph(
      Graph<V, E> target, final VertexFactory<V> vertexFactory, Map<String, V> resultMap) {
    if (size < 1) {
      return;
    }

    // A little trickery to intercept the rim generation.  This is
    // necessary since target may be initially non-empty, meaning we can't
    // rely on its vertex set after the rim is generated.
    final Collection<V> rim = new ArrayList<V>();
    VertexFactory<V> rimVertexFactory =
        new VertexFactory<V>() {
          public V createVertex() {
            V vertex = vertexFactory.createVertex();
            rim.add(vertex);

            return vertex;
          }
        };

    RingGraphGenerator<V, E> ringGenerator = new RingGraphGenerator<V, E>(size - 1);
    ringGenerator.generateGraph(target, rimVertexFactory, resultMap);

    V hubVertex = vertexFactory.createVertex();
    target.addVertex(hubVertex);

    if (resultMap != null) {
      resultMap.put(HUB_VERTEX, hubVertex);
    }

    for (V rimVertex : rim) {
      if (inwardSpokes) {
        target.addEdge(rimVertex, hubVertex);
      } else {
        target.addEdge(hubVertex, rimVertex);
      }
    }
  }
  /**
   * Runs the algorithm on the input graph and returns the match edge set.
   *
   * @return set of Edges
   */
  private Set<E> findMatch() {
    Set<E> result = new ArrayUnenforcedSet<>();
    match = new HashMap<>();
    path = new HashMap<>();
    contracted = new HashMap<>();

    for (V i : graph.vertexSet()) {
      // Any augmenting path should start with _exposed_ vertex
      // (vertex may not escape match-set being added once)
      if (!match.containsKey(i)) {
        // Match is maximal iff graph G contains no more augmenting paths
        V v = findPath(i);
        while (v != null) {
          V pv = path.get(v);
          V ppv = match.get(pv);
          match.put(v, pv);
          match.put(pv, v);
          v = ppv;
        }
      }
    }

    Set<V> seen = new HashSet<>();
    graph
        .vertexSet()
        .stream()
        .filter(v -> !seen.contains(v) && match.containsKey(v))
        .forEach(
            v -> {
              seen.add(v);
              seen.add(match.get(v));
              result.add(graph.getEdge(v, match.get(v)));
            });

    return result;
  }
示例#19
0
 public int getVertexNumber(V v) {
   return mapVertexToOrder.get(v);
 }
示例#20
0
 public void testCornerCases() {
   DirectedWeightedMultigraph<Integer, DefaultWeightedEdge> simple =
       new DirectedWeightedMultigraph<>(DefaultWeightedEdge.class);
   simple.addVertex(0);
   simple.addVertex(1);
   DefaultWeightedEdge e = simple.addEdge(0, 1);
   try {
     new EdmondsKarpMFImpl<Integer, DefaultWeightedEdge>(null);
     fail();
   } catch (NullPointerException ex) {
   }
   try {
     new EdmondsKarpMFImpl<>(simple, -0.1);
     fail();
   } catch (IllegalArgumentException ex) {
   }
   try {
     simple.setEdgeWeight(e, -1.0);
     new EdmondsKarpMFImpl<>(simple);
     fail();
   } catch (IllegalArgumentException ex) {
   }
   try {
     simple.setEdgeWeight(e, 1.0);
     MaximumFlowAlgorithm<Integer, DefaultWeightedEdge> solver = new EdmondsKarpMFImpl<>(simple);
     Map<DefaultWeightedEdge, Double> flow = solver.buildMaximumFlow(0, 1).getFlow();
     flow.put(e, 25.0);
     fail();
   } catch (UnsupportedOperationException ex) {
   }
   try {
     MaximumFlowAlgorithm<Integer, DefaultWeightedEdge> solver = new EdmondsKarpMFImpl<>(simple);
     solver.buildMaximumFlow(2, 0);
     fail();
   } catch (IllegalArgumentException ex) {
   }
   try {
     MaximumFlowAlgorithm<Integer, DefaultWeightedEdge> solver = new EdmondsKarpMFImpl<>(simple);
     solver.buildMaximumFlow(1, 2);
     fail();
   } catch (IllegalArgumentException ex) {
   }
   try {
     MaximumFlowAlgorithm<Integer, DefaultWeightedEdge> solver = new EdmondsKarpMFImpl<>(simple);
     solver.buildMaximumFlow(0, 0);
     fail();
   } catch (IllegalArgumentException ex) {
   }
   try {
     MaximumFlowAlgorithm<Integer, DefaultWeightedEdge> solver = new EdmondsKarpMFImpl<>(simple);
     solver.buildMaximumFlow(null, 0);
     fail();
   } catch (IllegalArgumentException ex) {
   }
   try {
     MaximumFlowAlgorithm<Integer, DefaultWeightedEdge> solver = new EdmondsKarpMFImpl<>(simple);
     solver.buildMaximumFlow(0, null);
     fail();
   } catch (IllegalArgumentException ex) {
   }
 }
  private V findPath(V root) {
    Set<V> used = new HashSet<>();
    Queue<V> q = new ArrayDeque<>();

    // Expand graph back from its contracted state
    path.clear();
    contracted.clear();

    graph.vertexSet().forEach(vertex -> contracted.put(vertex, vertex));

    used.add(root);
    q.add(root);

    while (!q.isEmpty()) {
      V v = q.remove();

      for (E e : graph.edgesOf(v)) {
        V to = graph.getEdgeSource(e);

        if (to.equals(v)) {
          to = graph.getEdgeTarget(e);
        }

        if ((contracted.get(v).equals(contracted.get(to))) || to.equals(match.get(v))) {
          continue;
        }

        // Check whether we've hit a 'blossom'
        if ((to.equals(root)) || ((match.containsKey(to)) && (path.containsKey(match.get(to))))) {
          V stem = lowestCommonAncestor(v, to);

          Set<V> blossom = new HashSet<>();

          markPath(v, to, stem, blossom);
          markPath(to, v, stem, blossom);

          graph
              .vertexSet()
              .stream()
              .filter(i -> contracted.containsKey(i) && blossom.contains(contracted.get(i)))
              .forEach(
                  i -> {
                    contracted.put(i, stem);
                    if (!used.contains(i)) {
                      used.add(i);
                      q.add(i);
                    }
                  });

          // Check whether we've had hit a loop (of even length (!) presumably)
        } else if (!path.containsKey(to)) {
          path.put(to, v);

          if (!match.containsKey(to)) {
            return to;
          }

          to = match.get(to);

          used.add(to);
          q.add(to);
        }
      }
    }
    return null;
  }
  /**
   * Compute the minimal triangulation of the graph. Implementation of Algorithm MCS-M+ as described
   * in Berry et al. (2010), DOI:10.3390/a3020197 <a href="http://www.mdpi.com/1999-4893/3/2/197">
   * http://www.mdpi.com/1999-4893/3/2/197</a>
   */
  private void computeMinimalTriangulation() {
    // initialize chordGraph with same vertices as graph
    chordalGraph = new SimpleGraph<>(graph.getEdgeFactory());
    for (V v : graph.vertexSet()) {
      chordalGraph.addVertex(v);
    }

    // initialize g' as subgraph of graph (same vertices and edges)
    final UndirectedGraph<V, E> gprime = copyAsSimpleGraph(graph);
    int s = -1;
    generators = new ArrayList<>();
    meo = new LinkedList<>();

    final Map<V, Integer> vertexLabels = new HashMap<>();
    for (V v : gprime.vertexSet()) {
      vertexLabels.put(v, 0);
    }
    for (int i = 1, n = graph.vertexSet().size(); i <= n; i++) {
      V v = getMaxLabelVertex(vertexLabels);
      LinkedList<V> Y = new LinkedList<>(Graphs.neighborListOf(gprime, v));

      if (vertexLabels.get(v) <= s) {
        generators.add(v);
      }

      s = vertexLabels.get(v);

      // Mark x reached and all other vertices of gprime unreached
      HashSet<V> reached = new HashSet<>();
      reached.add(v);

      // mark neighborhood of x reached and add to reach(label(y))
      HashMap<Integer, HashSet<V>> reach = new HashMap<>();

      // mark y reached and add y to reach
      for (V y : Y) {
        reached.add(y);
        addToReach(vertexLabels.get(y), y, reach);
      }

      for (int j = 0; j < graph.vertexSet().size(); j++) {
        if (!reach.containsKey(j)) {
          continue;
        }
        while (reach.get(j).size() > 0) {
          // remove a vertex y from reach(j)
          V y = reach.get(j).iterator().next();
          reach.get(j).remove(y);

          for (V z : Graphs.neighborListOf(gprime, y)) {
            if (!reached.contains(z)) {
              reached.add(z);
              if (vertexLabels.get(z) > j) {
                Y.add(z);
                E fillEdge = graph.getEdgeFactory().createEdge(v, z);
                fillEdges.add(fillEdge);
                addToReach(vertexLabels.get(z), z, reach);
              } else {
                addToReach(j, z, reach);
              }
            }
          }
        }
      }

      for (V y : Y) {
        chordalGraph.addEdge(v, y);
        vertexLabels.put(y, vertexLabels.get(y) + 1);
      }

      meo.addLast(v);
      gprime.removeVertex(v);
      vertexLabels.remove(v);
    }
  }
示例#23
0
 /** @see Graph#containsEdge(Object) */
 public boolean containsEdge(E e) {
   return edgeMap.containsKey(e);
 }
示例#24
0
 private IntrusiveEdge getIntrusiveEdge(E e) {
   if (e instanceof IntrusiveEdge) {
     return (IntrusiveEdge) e;
   }
   return edgeMap.get(e);
 }
 /**
  * Access the data stored for a seen vertex.
  *
  * @param vertex a vertex which has already been seen.
  * @return data associated with the seen vertex or <code>null</code> if no data was associated
  *     with the vertex. A <code>null</code> return can also indicate that the vertex was
  *     explicitly associated with <code>
  * null</code>.
  */
 protected D getSeenData(V vertex) {
   return seen.get(vertex);
 }
 /**
  * Determines whether a vertex has been seen yet by this traversal.
  *
  * @param vertex vertex in question
  * @return <tt>true</tt> if vertex has already been seen
  */
 protected boolean isSeenVertex(Object vertex) {
   return seen.containsKey(vertex);
 }
 /**
  * Stores iterator-dependent data for a vertex that has been seen.
  *
  * @param vertex a vertex which has been seen.
  * @param data data to be associated with the seen vertex.
  * @return previous value associated with specified vertex or <code>
  * null</code> if no data was associated with the vertex. A <code>
  * null</code> return can also indicate that the vertex was explicitly associated with <code>null
  *     </code>.
  */
 protected D putSeenData(V vertex, D data) {
   return seen.put(vertex, data);
 }