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

com.twitter.cassovary.graph.DirectedGraphUtils.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
 * file except in compliance with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package com.twitter.cassovary.graph

import com.twitter.cassovary.graph.GraphDir._
import scala.util.Sorting
import scala.collection.mutable

/**
 * This class contains some common utilities and convenience functions for directed graphs.
 * It differs from {@code GraphUtils} because it works on a directed graph (which provides
 * some other things, such as an iterator on top of the underlying {@code Graph})
 */
class DirectedGraphUtils[+V <: Node](val directedGraph: DirectedGraph[V]) extends GraphUtils(directedGraph) {

  /** *
    * Returns the number of mutual edges in the graph (i.e., edges of type a->b and b->a both exist)
    * Warning: creates a copy of all edges, so it is memory inefficient. Better would be to spill
    * edges to disk intelligently and do an external sort.
    * @return number of mutual edges
    */
  def getNumMutualEdges: Long = {
    val edges = mutable.ArrayBuffer[Long]()
    if (directedGraph.isDirStored(InDir) && directedGraph.isDirStored(OutDir)) {
      val mutualEdges = directedGraph.foldLeft(0L) { (sum, node) => sum + getNumMutualEdgesBothDirs(node) }
      mutualEdges/2
    } else {
      val indir = directedGraph.isDirStored(InDir)
      directedGraph.foreach { node =>
        val neighbors = if (indir) node.inboundNodes else node.outboundNodes
        neighbors.foreach { destNodeId =>
          val sourceId = node.id.toLong
          val destId = destNodeId.toLong
          val edge = if (sourceId < destId) (sourceId << 32) | destId
          else (destId << 32) | sourceId
          edges += edge
        }
      }
      val edgesArr = edges.toArray
      Sorting.quickSort(edgesArr)
      val (numMutualEdges, _) = edgesArr.foldLeft((0L, -1L)) { case ((sum, prev), curr) =>
        val n = if (prev == curr) 1L else 0L
        (sum + n, curr)
      }
      numMutualEdges
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy