org.apache.flink.graph.scala.Graph.scala Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.flink.graph.scala
import org.apache.flink.api.common.functions.{FilterFunction, MapFunction}
import org.apache.flink.api.common.typeinfo.TypeInformation
import org.apache.flink.api.java.{tuple => jtuple}
import org.apache.flink.api.scala._
import org.apache.flink.graph._
import org.apache.flink.graph.asm.translate.TranslateFunction
import org.apache.flink.graph.gsa.{ApplyFunction, GSAConfiguration, SumFunction, GatherFunction => GSAGatherFunction}
import org.apache.flink.graph.pregel.{ComputeFunction, MessageCombiner, VertexCentricConfiguration}
import org.apache.flink.graph.spargel.{ScatterFunction, ScatterGatherConfiguration, GatherFunction => SpargelGatherFunction}
import org.apache.flink.graph.validation.GraphValidator
import org.apache.flink.types.{LongValue, NullValue}
import org.apache.flink.util.Preconditions
import org.apache.flink.{graph => jg}
import _root_.scala.collection.JavaConverters._
import _root_.scala.reflect.ClassTag
object Graph {
/**
* Creates a Graph from a DataSet of vertices and a DataSet of edges.
*/
def fromDataSet[K: TypeInformation : ClassTag, VV: TypeInformation : ClassTag, EV:
TypeInformation : ClassTag](vertices: DataSet[Vertex[K, VV]], edges: DataSet[Edge[K, EV]],
env: ExecutionEnvironment): Graph[K, VV, EV] = {
wrapGraph(jg.Graph.fromDataSet[K, VV, EV](vertices.javaSet, edges.javaSet, env.getJavaEnv))
}
/**
* Creates a Graph from a DataSet of edges.
* Vertices are created automatically and their values are set to NullValue.
*/
def fromDataSet[K: TypeInformation : ClassTag, EV: TypeInformation : ClassTag]
(edges: DataSet[Edge[K, EV]], env: ExecutionEnvironment): Graph[K, NullValue, EV] = {
wrapGraph(jg.Graph.fromDataSet[K, EV](edges.javaSet, env.getJavaEnv))
}
/**
* Creates a graph from a DataSet of edges.
* Vertices are created automatically and their values are set by applying the provided
* vertexValueInitializer map function to the vertex ids.
*/
def fromDataSet[K: TypeInformation : ClassTag, VV: TypeInformation : ClassTag, EV:
TypeInformation : ClassTag](edges: DataSet[Edge[K, EV]],
vertexValueInitializer: MapFunction[K, VV], env: ExecutionEnvironment): Graph[K, VV, EV] = {
wrapGraph(jg.Graph.fromDataSet[K, VV, EV](edges.javaSet, vertexValueInitializer,
env.getJavaEnv))
}
/**
* Creates a Graph from a Seq of vertices and a Seq of edges.
*/
def fromCollection[K: TypeInformation : ClassTag, VV: TypeInformation : ClassTag, EV:
TypeInformation : ClassTag](vertices: Seq[Vertex[K, VV]], edges: Seq[Edge[K, EV]], env:
ExecutionEnvironment): Graph[K, VV, EV] = {
wrapGraph(jg.Graph.fromCollection[K, VV, EV](vertices.asJavaCollection, edges
.asJavaCollection, env.getJavaEnv))
}
/**
* Creates a Graph from a Seq of edges.
* Vertices are created automatically and their values are set to NullValue.
*/
def fromCollection[K: TypeInformation : ClassTag, EV: TypeInformation : ClassTag]
(edges: Seq[Edge[K, EV]], env: ExecutionEnvironment): Graph[K, NullValue, EV] = {
wrapGraph(jg.Graph.fromCollection[K, EV](edges.asJavaCollection, env.getJavaEnv))
}
/**
* Creates a graph from a Seq of edges.
* Vertices are created automatically and their values are set by applying the provided
* vertexValueInitializer map function to the vertex ids.
*/
def fromCollection[K: TypeInformation : ClassTag, VV: TypeInformation : ClassTag, EV:
TypeInformation : ClassTag](edges: Seq[Edge[K, EV]], vertexValueInitializer: MapFunction[K, VV],
env: ExecutionEnvironment): Graph[K, VV, EV] = {
wrapGraph(jg.Graph.fromCollection[K, VV, EV](edges.asJavaCollection, vertexValueInitializer,
env.getJavaEnv))
}
/**
* Creates a graph from DataSets of tuples for vertices and for edges.
* The first field of the Tuple2 vertex object will become the vertex ID
* and the second field will become the vertex value.
* The first field of the Tuple3 object for edges will become the source ID,
* the second field will become the target ID, and the third field will become
* the edge value.
*/
def fromTupleDataSet[K: TypeInformation : ClassTag, VV: TypeInformation : ClassTag, EV:
TypeInformation : ClassTag](vertices: DataSet[(K, VV)], edges: DataSet[(K, K, EV)],
env: ExecutionEnvironment): Graph[K, VV, EV] = {
val javaTupleVertices = vertices.map((v: (K, VV)) => new jtuple.Tuple2(v._1, v._2)).javaSet
val javaTupleEdges = edges.map((v: (K, K, EV)) => new jtuple.Tuple3(v._1, v._2, v._3)).javaSet
wrapGraph(jg.Graph.fromTupleDataSet[K, VV, EV](javaTupleVertices, javaTupleEdges,
env.getJavaEnv))
}
/**
* Creates a Graph from a DataSet of Tuples representing the edges.
* The first field of the Tuple3 object for edges will become the source ID,
* the second field will become the target ID, and the third field will become
* the edge value.
* Vertices are created automatically and their values are set to NullValue.
*/
def fromTupleDataSet[K: TypeInformation : ClassTag, EV: TypeInformation : ClassTag]
(edges: DataSet[(K, K, EV)], env: ExecutionEnvironment): Graph[K, NullValue, EV] = {
val javaTupleEdges = edges.map((v: (K, K, EV)) => new jtuple.Tuple3(v._1, v._2, v._3)).javaSet
wrapGraph(jg.Graph.fromTupleDataSet[K, EV](javaTupleEdges, env.getJavaEnv))
}
/**
* Creates a Graph from a DataSet of Tuples representing the edges.
* The first field of the Tuple3 object for edges will become the source ID,
* the second field will become the target ID, and the third field will become
* the edge value.
* Vertices are created automatically and their values are set by applying the provided
* vertexValueInitializer map function to the vertex ids.
*/
def fromTupleDataSet[K: TypeInformation : ClassTag, VV: TypeInformation : ClassTag, EV:
TypeInformation : ClassTag](edges: DataSet[(K, K, EV)],
vertexValueInitializer: MapFunction[K, VV], env: ExecutionEnvironment): Graph[K, VV, EV] = {
val javaTupleEdges = edges.map((v: (K, K, EV)) => new jtuple.Tuple3(v._1, v._2, v._3)).javaSet
wrapGraph(jg.Graph.fromTupleDataSet[K, VV, EV](javaTupleEdges, vertexValueInitializer,
env.getJavaEnv))
}
/**
* Creates a Graph from a DataSet of Tuple2's representing the edges.
* The first field of the Tuple2 object for edges will become the source ID,
* the second field will become the target ID. The edge value will be set to NullValue.
* Vertices are created automatically and their values are set to NullValue.
*/
def fromTuple2DataSet[K: TypeInformation : ClassTag](edges: DataSet[(K, K)],
env: ExecutionEnvironment): Graph[K, NullValue, NullValue] = {
val javaTupleEdges = edges.map((v: (K, K)) => new jtuple.Tuple2(v._1, v._2)).javaSet
wrapGraph(jg.Graph.fromTuple2DataSet[K](javaTupleEdges, env.getJavaEnv))
}
/**
* Creates a Graph from a DataSet of Tuple2's representing the edges.
* The first field of the Tuple2 object for edges will become the source ID,
* the second field will become the target ID. The edge value will be set to NullValue.
* Vertices are created automatically and their values are set by applying the provided
* vertexValueInitializer map function to the vertex IDs.
*/
def fromTuple2DataSet[K: TypeInformation : ClassTag, VV: TypeInformation : ClassTag]
(edges: DataSet[(K, K)], vertexValueInitializer: MapFunction[K, VV],
env: ExecutionEnvironment): Graph[K, VV, NullValue] = {
val javaTupleEdges = edges.map((v: (K, K)) => new jtuple.Tuple2(v._1, v._2)).javaSet
wrapGraph(jg.Graph.fromTuple2DataSet[K, VV](javaTupleEdges, vertexValueInitializer,
env.getJavaEnv))
}
/** Creates a Graph from a CSV file of edges.
*
* The edge value is read from the CSV file if [[EV]] is not of type [[NullValue]]. Otherwise the
* edge value is set to [[NullValue]].
*
* If the vertex value type [[VV]] is specified (unequal [[NullValue]]), then the vertex values
* are read from the file specified by pathVertices. If the path has not been specified then the
* vertexValueInitializer is used to initialize the vertex values of the vertices extracted from
* the set of edges. If the vertexValueInitializer has not been set either, then the method
* fails.
*
* @param env The Execution Environment.
* @param pathEdges The file path containing the edges.
* @param pathVertices The file path containing the vertices.
* @param lineDelimiterVertices The string that separates lines in the vertices file. It defaults
* to newline.
* @param fieldDelimiterVertices The string that separates vertex Ids from vertex values in the
* vertices file.
* @param quoteCharacterVertices The character to use for quoted String parsing in the vertices
* file. Disabled by default.
* @param ignoreFirstLineVertices Whether the first line in the vertices file should be ignored.
* @param ignoreCommentsVertices Lines that start with the given String in the vertices file
* are ignored, disabled by default.
* @param lenientVertices Whether the parser should silently ignore malformed lines in the
* vertices file.
* @param includedFieldsVertices The fields in the vertices file that should be read. By default
* all fields are read.
* @param lineDelimiterEdges The string that separates lines in the edges file. It defaults to
* newline.
* @param fieldDelimiterEdges The string that separates fields in the edges file.
* @param quoteCharacterEdges The character to use for quoted String parsing in the edges file.
* Disabled by default.
* @param ignoreFirstLineEdges Whether the first line in the vertices file should be ignored.
* @param ignoreCommentsEdges Lines that start with the given String in the edges file are
* ignored, disabled by default.
* @param lenientEdges Whether the parser should silently ignore malformed lines in the edges
* file.
* @param includedFieldsEdges The fields in the edges file that should be read. By default all
* fields are read.
* @param vertexValueInitializer If no vertex values are provided, this mapper can be used to
* initialize them, by applying a map transformation on the vertex
* IDs.
* @tparam K Vertex key type
* @tparam VV Vertex value type
* @tparam EV Edge value type
* @return Graph with vertices and edges read from the given files.
*/
// scalastyle:off
// This method exceeds the max allowed number of parameters -->
def fromCsvReader[
K: TypeInformation : ClassTag,
VV: TypeInformation : ClassTag,
EV: TypeInformation : ClassTag](
env: ExecutionEnvironment,
pathEdges: String,
pathVertices: String = null,
lineDelimiterVertices: String = "\n",
fieldDelimiterVertices: String = ",",
quoteCharacterVertices: Character = null,
ignoreFirstLineVertices: Boolean = false,
ignoreCommentsVertices: String = null,
lenientVertices: Boolean = false,
includedFieldsVertices: Array[Int] = null,
lineDelimiterEdges: String = "\n",
fieldDelimiterEdges: String = ",",
quoteCharacterEdges: Character = null,
ignoreFirstLineEdges: Boolean = false,
ignoreCommentsEdges: String = null,
lenientEdges: Boolean = false,
includedFieldsEdges: Array[Int] = null,
vertexValueInitializer: MapFunction[K, VV] = null)
: Graph[K, VV, EV] = {
Preconditions.checkNotNull(pathEdges)
val evClassTag = implicitly[ClassTag[EV]]
val vvClassTag = implicitly[ClassTag[VV]]
val edges = if (evClassTag.runtimeClass.equals(classOf[NullValue])) {
env.readCsvFile[(K, K)](
pathEdges,
lineDelimiterEdges,
fieldDelimiterEdges,
quoteCharacterEdges,
ignoreFirstLineEdges,
ignoreCommentsEdges,
lenientEdges,
includedFieldsEdges)
.map((edge: (K, K)) => (edge._1, edge._2, NullValue.getInstance))
.asInstanceOf[DataSet[(K, K, EV)]]
} else {
env.readCsvFile[(K, K, EV)](
pathEdges,
lineDelimiterEdges,
fieldDelimiterEdges,
quoteCharacterEdges,
ignoreFirstLineEdges,
ignoreCommentsEdges,
lenientEdges,
includedFieldsEdges)
}
if (vvClassTag.runtimeClass.equals(classOf[NullValue])) {
fromTupleDataSet[K, EV](edges, env).asInstanceOf[Graph[K, VV, EV]]
} else {
if (pathVertices != null) {
val vertices = env.readCsvFile[(K, VV)](pathVertices, lineDelimiterVertices,
fieldDelimiterVertices, quoteCharacterVertices, ignoreFirstLineVertices,
ignoreCommentsVertices, lenientVertices, includedFieldsVertices)
fromTupleDataSet[K, VV, EV](vertices, edges, env)
} else if (vertexValueInitializer != null) {
fromTupleDataSet[K, VV, EV](edges, vertexValueInitializer, env)
} else {
throw new IllegalArgumentException("Path vertices path and vertex value initialzier must" +
"not be null if the vertex value type is not NullValue.")
}
}
}
// scalastyle:on
}
/**
* Represents a graph consisting of [[Edge]] edges and [[Vertex]] vertices.
*
* @param jgraph the underlying java api Graph.
* @tparam K the key type for vertex and edge identifiers
* @tparam VV the value type for vertices
* @tparam EV the value type for edges
* @see org.apache.flink.graph.Edge
* @see org.apache.flink.graph.Vertex
*/
final class Graph[K: TypeInformation : ClassTag, VV: TypeInformation : ClassTag, EV:
TypeInformation : ClassTag](jgraph: jg.Graph[K, VV, EV]) {
private[flink] def getWrappedGraph = jgraph
private[flink] def clean[F <: AnyRef](f: F, checkSerializable: Boolean = true): F = {
if (jgraph.getContext.getConfig.isClosureCleanerEnabled) {
ClosureCleaner.clean(f, checkSerializable, jgraph.getContext.getConfig.getClosureCleanerLevel)
}
ClosureCleaner.ensureSerializable(f)
f
}
/**
* @return the vertex DataSet.
*/
def getVertices = wrap(jgraph.getVertices)
/**
* @return the edge DataSet.
*/
def getEdges = wrap(jgraph.getEdges)
/**
* @return the vertex DataSet as Tuple2.
*/
def getVerticesAsTuple2(): DataSet[(K, VV)] = {
wrap(jgraph.getVerticesAsTuple2).map(
(v: jtuple.Tuple2[K, VV]) => (v.f0, v.f1))
}
/**
* @return the edge DataSet as Tuple3.
*/
def getEdgesAsTuple3(): DataSet[(K, K, EV)] = {
wrap(jgraph.getEdgesAsTuple3).map(
(e: jtuple.Tuple3[K, K, EV]) =>
(e.f0, e.f1, e.f2))
}
/**
* @return a DataSet of Triplets,
* consisting of (srcVertexId, trgVertexId, srcVertexValue, trgVertexValue, edgeValue)
*/
def getTriplets(): DataSet[Triplet[K, VV, EV]] = {
wrap(jgraph.getTriplets())
}
/**
* Apply a function to the attribute of each vertex in the graph.
*
* @param mapper the map function to apply.
* @return a new graph
*/
def mapVertices[NV: TypeInformation : ClassTag](mapper: MapFunction[Vertex[K, VV], NV]):
Graph[K, NV, EV] = {
new Graph[K, NV, EV](jgraph.mapVertices[NV](
mapper,
createTypeInformation[Vertex[K, NV]]
))
}
/**
* Apply a function to the attribute of each vertex in the graph.
*
* @param fun the map function to apply.
* @return a new graph
*/
def mapVertices[NV: TypeInformation : ClassTag](fun: Vertex[K, VV] => NV): Graph[K, NV, EV] = {
val mapper: MapFunction[Vertex[K, VV], NV] = new MapFunction[Vertex[K, VV], NV] {
val cleanFun = clean(fun)
def map(in: Vertex[K, VV]): NV = cleanFun(in)
}
new Graph[K, NV, EV](jgraph.mapVertices[NV](mapper, createTypeInformation[Vertex[K, NV]]))
}
/**
* Apply a function to the attribute of each edge in the graph.
*
* @param mapper the map function to apply.
* @return a new graph
*/
def mapEdges[NV: TypeInformation : ClassTag](mapper: MapFunction[Edge[K, EV], NV]): Graph[K,
VV, NV] = {
new Graph[K, VV, NV](jgraph.mapEdges[NV](
mapper,
createTypeInformation[Edge[K, NV]]
))
}
/**
* Apply a function to the attribute of each edge in the graph.
*
* @param fun the map function to apply.
* @return a new graph
*/
def mapEdges[NV: TypeInformation : ClassTag](fun: Edge[K, EV] => NV): Graph[K, VV, NV] = {
val mapper: MapFunction[Edge[K, EV], NV] = new MapFunction[Edge[K, EV], NV] {
val cleanFun = clean(fun)
def map(in: Edge[K, EV]): NV = cleanFun(in)
}
new Graph[K, VV, NV](jgraph.mapEdges[NV](mapper, createTypeInformation[Edge[K, NV]]))
}
/**
* Translate vertex and edge IDs using the given MapFunction.
*
* @param translator implements conversion from K to NEW
* @return graph with translated vertex and edge IDs
*/
def translateGraphIds[NEW: TypeInformation : ClassTag](translator: TranslateFunction[K, NEW]):
Graph[NEW, VV, EV] = {
new Graph[NEW, VV, EV](jgraph.translateGraphIds(translator))
}
/**
* Translate vertex and edge IDs using the given function.
*
* @param fun implements conversion from K to NEW
* @return graph with translated vertex and edge IDs
*/
def translateGraphIds[NEW: TypeInformation : ClassTag](fun: (K, NEW) => NEW):
Graph[NEW, VV, EV] = {
val translator: TranslateFunction[K, NEW] = new TranslateFunction[K, NEW] {
val cleanFun = clean(fun)
def translate(in: K, reuse: NEW): NEW = cleanFun(in, reuse)
}
new Graph[NEW, VV, EV](jgraph.translateGraphIds(translator))
}
/**
* Translate vertex values using the given MapFunction.
*
* @param translator implements conversion from VV to NEW
* @return graph with translated vertex values
*/
def translateVertexValues[NEW: TypeInformation : ClassTag](translator:
TranslateFunction[VV, NEW]): Graph[K, NEW, EV] = {
new Graph[K, NEW, EV](jgraph.translateVertexValues(translator))
}
/**
* Translate vertex values using the given function.
*
* @param fun implements conversion from VV to NEW
* @return graph with translated vertex values
*/
def translateVertexValues[NEW: TypeInformation : ClassTag](fun: (VV, NEW) => NEW):
Graph[K, NEW, EV] = {
val translator: TranslateFunction[VV, NEW] = new TranslateFunction[VV, NEW] {
val cleanFun = clean(fun)
def translate(in: VV, reuse: NEW): NEW = cleanFun(in, reuse)
}
new Graph[K, NEW, EV](jgraph.translateVertexValues(translator))
}
/**
* Translate edge values using the given MapFunction.
*
* @param translator implements conversion from EV to NEW
* @return graph with translated edge values
*/
def translateEdgeValues[NEW: TypeInformation : ClassTag](translator: TranslateFunction[EV, NEW]):
Graph[K, VV, NEW] = {
new Graph[K, VV, NEW](jgraph.translateEdgeValues(translator))
}
/**
* Translate edge values using the given function.
*
* @param fun implements conversion from EV to NEW
* @return graph with translated edge values
*/
def translateEdgeValues[NEW: TypeInformation : ClassTag](fun: (EV, NEW) => NEW):
Graph[K, VV, NEW] = {
val translator: TranslateFunction[EV, NEW] = new TranslateFunction[EV, NEW] {
val cleanFun = clean(fun)
def translate(in: EV, reuse: NEW): NEW = cleanFun(in, reuse)
}
new Graph[K, VV, NEW](jgraph.translateEdgeValues(translator))
}
/**
* Joins the vertex DataSet of this graph with an input Tuple2 DataSet and applies
* a user-defined transformation on the values of the matched records.
* The vertex ID and the first field of the Tuple2 DataSet are used as the join keys.
*
* @param inputDataSet the Tuple2 DataSet to join with.
* The first field of the Tuple2 is used as the join key and the second field is passed
* as a parameter to the transformation function.
* @param vertexJoinFunction the transformation function to apply.
* The first parameter is the current vertex value and the second parameter is the value
* of the matched Tuple2 from the input DataSet.
* @return a new Graph, where the vertex values have been updated according to the
* result of the vertexJoinFunction.
* @tparam T the type of the second field of the input Tuple2 DataSet.
*/
def joinWithVertices[T: TypeInformation](inputDataSet: DataSet[(K, T)],
vertexJoinFunction: VertexJoinFunction[VV, T]): Graph[K, VV, EV] = {
val javaTupleSet = inputDataSet.map(
(i: (K, T)) => new jtuple.Tuple2(i._1, i._2)).javaSet
wrapGraph(jgraph.joinWithVertices[T](javaTupleSet, vertexJoinFunction))
}
/**
* Joins the vertex DataSet of this graph with an input Tuple2 DataSet and applies
* a user-defined transformation on the values of the matched records.
* The vertex ID and the first field of the Tuple2 DataSet are used as the join keys.
*
* @param inputDataSet the Tuple2 DataSet to join with.
* The first field of the Tuple2 is used as the join key and the second field is passed
* as a parameter to the transformation function.
* @param fun the transformation function to apply.
* The first parameter is the current vertex value and the second parameter is the value
* of the matched Tuple2 from the input DataSet.
* @return a new Graph, where the vertex values have been updated according to the
* result of the vertexJoinFunction.
* @tparam T the type of the second field of the input Tuple2 DataSet.
*/
def joinWithVertices[T: TypeInformation](inputDataSet: DataSet[(K, T)], fun: (VV, T) => VV):
Graph[K, VV, EV] = {
val newVertexJoin = new VertexJoinFunction[VV, T]() {
val cleanFun = clean(fun)
override def vertexJoin(vertexValue: VV, inputValue: T): VV = {
cleanFun(vertexValue, inputValue)
}
}
val javaTupleSet = inputDataSet.map(
(i: (K, T)) => new jtuple.Tuple2(i._1, i._2)).javaSet
wrapGraph(jgraph.joinWithVertices[T](javaTupleSet, newVertexJoin))
}
/**
* Joins the edge DataSet with an input DataSet on the composite key of both
* source and target IDs and applies a user-defined transformation on the values
* of the matched records. The first two fields of the input DataSet are used as join keys.
*
* @param inputDataSet the DataSet to join with.
* The first two fields of the Tuple3 are used as the composite join key
* and the third field is passed as a parameter to the transformation function.
* @param edgeJoinFunction the transformation function to apply.
* The first parameter is the current edge value and the second parameter is the value
* of the matched Tuple3 from the input DataSet.
* @tparam T the type of the third field of the input Tuple3 DataSet.
* @return a new Graph, where the edge values have been updated according to the
* result of the edgeJoinFunction.
*/
def joinWithEdges[T: TypeInformation](inputDataSet: DataSet[(K, K, T)],
edgeJoinFunction: EdgeJoinFunction[EV, T]): Graph[K, VV, EV] = {
val javaTupleSet = inputDataSet.map(
(i: (K, K, T)) => new jtuple.Tuple3(i._1, i._2, i._3)).javaSet
wrapGraph(jgraph.joinWithEdges[T](javaTupleSet, edgeJoinFunction))
}
/**
* Joins the edge DataSet with an input DataSet on the composite key of both
* source and target IDs and applies a user-defined transformation on the values
* of the matched records. The first two fields of the input DataSet are used as join keys.
*
* @param inputDataSet the DataSet to join with.
* The first two fields of the Tuple3 are used as the composite join key
* and the third field is passed as a parameter to the transformation function.
* @param fun the transformation function to apply.
* The first parameter is the current edge value and the second parameter is the value
* of the matched Tuple3 from the input DataSet.
* @tparam T the type of the third field of the input Tuple3 DataSet.
* @return a new Graph, where the edge values have been updated according to the
* result of the edgeJoinFunction.
*/
def joinWithEdges[T: TypeInformation](inputDataSet: DataSet[(K, K, T)], fun: (EV, T) => EV):
Graph[K, VV, EV] = {
val newEdgeJoin = new EdgeJoinFunction[EV, T]() {
val cleanFun = clean(fun)
override def edgeJoin(edgeValue: EV, inputValue: T): EV = {
cleanFun(edgeValue, inputValue)
}
}
val javaTupleSet = inputDataSet.map(
(i: (K, K, T)) => new jtuple.Tuple3(i._1, i._2, i._3)).javaSet
wrapGraph(jgraph.joinWithEdges[T](javaTupleSet, newEdgeJoin))
}
/**
* Joins the edge DataSet with an input Tuple2 DataSet and applies a user-defined transformation
* on the values of the matched records.
* The source ID of the edges input and the first field of the input DataSet
* are used as join keys.
*
* @param inputDataSet the DataSet to join with.
* The first field of the Tuple2 is used as the join key
* and the second field is passed as a parameter to the transformation function.
* @param edgeJoinFunction the transformation function to apply.
* The first parameter is the current edge value and the second parameter is the value
* of the matched Tuple2 from the input DataSet.
* @tparam T the type of the second field of the input Tuple2 DataSet.
* @return a new Graph, where the edge values have been updated according to the
* result of the edgeJoinFunction.
*/
def joinWithEdgesOnSource[T: TypeInformation](inputDataSet: DataSet[(K, T)],
edgeJoinFunction: EdgeJoinFunction[EV, T]): Graph[K, VV, EV] = {
val javaTupleSet = inputDataSet.map(
(i: (K, T)) => new jtuple.Tuple2(i._1, i._2)).javaSet
wrapGraph(jgraph.joinWithEdgesOnSource[T](javaTupleSet, edgeJoinFunction))
}
/**
* Joins the edge DataSet with an input Tuple2 DataSet and applies a user-defined transformation
* on the values of the matched records.
* The source ID of the edges input and the first field of the input DataSet
* are used as join keys.
*
* @param inputDataSet the DataSet to join with.
* The first field of the Tuple2 is used as the join key
* and the second field is passed as a parameter to the transformation function.
* @param fun the transformation function to apply.
* The first parameter is the current edge value and the second parameter is the value
* of the matched Tuple2 from the input DataSet.
* @tparam T the type of the second field of the input Tuple2 DataSet.
* @return a new Graph, where the edge values have been updated according to the
* result of the edgeJoinFunction.
*/
def joinWithEdgesOnSource[T: TypeInformation](inputDataSet: DataSet[(K, T)], fun: (EV, T) =>
EV): Graph[K, VV, EV] = {
val newEdgeJoin = new EdgeJoinFunction[EV, T]() {
val cleanFun = clean(fun)
override def edgeJoin(edgeValue: EV, inputValue: T): EV = {
cleanFun(edgeValue, inputValue)
}
}
val javaTupleSet = inputDataSet.map(
(i: (K, T)) => new jtuple.Tuple2(i._1, i._2)).javaSet
wrapGraph(jgraph.joinWithEdgesOnSource[T](javaTupleSet, newEdgeJoin))
}
/**
* Joins the edge DataSet with an input Tuple2 DataSet and applies a user-defined transformation
* on the values of the matched records.
* The target ID of the edges input and the first field of the input DataSet
* are used as join keys.
*
* @param inputDataSet the DataSet to join with.
* The first field of the Tuple2 is used as the join key
* and the second field is passed as a parameter to the transformation function.
* @param edgeJoinFunction the transformation function to apply.
* The first parameter is the current edge value and the second parameter is the value
* of the matched Tuple2 from the input DataSet.
* @tparam T the type of the second field of the input Tuple2 DataSet.
* @return a new Graph, where the edge values have been updated according to the
* result of the edgeJoinFunction.
*/
def joinWithEdgesOnTarget[T: TypeInformation](inputDataSet: DataSet[(K, T)],
edgeJoinFunction: EdgeJoinFunction[EV, T]): Graph[K, VV, EV] = {
val javaTupleSet = inputDataSet.map(
(i: (K, T)) => new jtuple.Tuple2(i._1, i._2)).javaSet
wrapGraph(jgraph.joinWithEdgesOnTarget[T](javaTupleSet, edgeJoinFunction))
}
/**
* Joins the edge DataSet with an input Tuple2 DataSet and applies a user-defined transformation
* on the values of the matched records.
* The target ID of the edges input and the first field of the input DataSet
* are used as join keys.
*
* @param inputDataSet the DataSet to join with.
* The first field of the Tuple2 is used as the join key
* and the second field is passed as a parameter to the transformation function.
* @param fun the transformation function to apply.
* The first parameter is the current edge value and the second parameter is the value
* of the matched Tuple2 from the input DataSet.
* @tparam T the type of the second field of the input Tuple2 DataSet.
* @return a new Graph, where the edge values have been updated according to the
* result of the edgeJoinFunction.
*/
def joinWithEdgesOnTarget[T: TypeInformation](inputDataSet: DataSet[(K, T)], fun: (EV, T) =>
EV): Graph[K, VV, EV] = {
val newEdgeJoin = new EdgeJoinFunction[EV, T]() {
val cleanFun = clean(fun)
override def edgeJoin(edgeValue: EV, inputValue:T): EV = {
cleanFun(edgeValue, inputValue)
}
}
val javaTupleSet = inputDataSet.map(
(i: (K, T)) => new jtuple.Tuple2(i._1, i._2)).javaSet
wrapGraph(jgraph.joinWithEdgesOnTarget[T](javaTupleSet, newEdgeJoin))
}
/**
* Apply filtering functions to the graph and return a sub-graph that
* satisfies the predicates for both vertices and edges.
*
* @param vertexFilter the filter function for vertices.
* @param edgeFilter the filter function for edges.
* @return the resulting sub-graph.
*/
def subgraph(vertexFilter: FilterFunction[Vertex[K, VV]], edgeFilter: FilterFunction[Edge[K,
EV]]) = {
wrapGraph(jgraph.subgraph(vertexFilter, edgeFilter))
}
/**
* Apply filtering functions to the graph and return a sub-graph that
* satisfies the predicates for both vertices and edges.
*
* @param vertexFilterFun the filter function for vertices.
* @param edgeFilterFun the filter function for edges.
* @return the resulting sub-graph.
*/
def subgraph(vertexFilterFun: Vertex[K, VV] => Boolean, edgeFilterFun: Edge[K, EV] =>
Boolean) = {
val vertexFilter = new FilterFunction[Vertex[K, VV]] {
val cleanVertexFun = clean(vertexFilterFun)
override def filter(value: Vertex[K, VV]): Boolean = cleanVertexFun(value)
}
val edgeFilter = new FilterFunction[Edge[K, EV]] {
val cleanEdgeFun = clean(edgeFilterFun)
override def filter(value: Edge[K, EV]): Boolean = cleanEdgeFun(value)
}
wrapGraph(jgraph.subgraph(vertexFilter, edgeFilter))
}
/**
* Apply a filtering function to the graph and return a sub-graph that
* satisfies the predicates only for the vertices.
*
* @param vertexFilter the filter function for vertices.
* @return the resulting sub-graph.
*/
def filterOnVertices(vertexFilter: FilterFunction[Vertex[K, VV]]) = {
wrapGraph(jgraph.filterOnVertices(vertexFilter))
}
/**
* Apply a filtering function to the graph and return a sub-graph that
* satisfies the predicates only for the vertices.
*
* @param vertexFilterFun the filter function for vertices.
* @return the resulting sub-graph.
*/
def filterOnVertices(vertexFilterFun: Vertex[K, VV] => Boolean) = {
val vertexFilter = new FilterFunction[Vertex[K, VV]] {
val cleanVertexFun = clean(vertexFilterFun)
override def filter(value: Vertex[K, VV]): Boolean = cleanVertexFun(value)
}
wrapGraph(jgraph.filterOnVertices(vertexFilter))
}
/**
* Apply a filtering function to the graph and return a sub-graph that
* satisfies the predicates only for the edges.
*
* @param edgeFilter the filter function for edges.
* @return the resulting sub-graph.
*/
def filterOnEdges(edgeFilter: FilterFunction[Edge[K, EV]]) = {
wrapGraph(jgraph.filterOnEdges(edgeFilter))
}
/**
* Apply a filtering function to the graph and return a sub-graph that
* satisfies the predicates only for the edges.
*
* @param edgeFilterFun the filter function for edges.
* @return the resulting sub-graph.
*/
def filterOnEdges(edgeFilterFun: Edge[K, EV] => Boolean) = {
val edgeFilter = new FilterFunction[Edge[K, EV]] {
val cleanEdgeFun = clean(edgeFilterFun)
override def filter(value: Edge[K, EV]): Boolean = cleanEdgeFun(value)
}
wrapGraph(jgraph.filterOnEdges(edgeFilter))
}
/**
* Return the in-degree of all vertices in the graph
*
* @return A DataSet of Tuple2
*/
def inDegrees(): DataSet[(K, LongValue)] = {
wrap(jgraph.inDegrees).map((i: jtuple.Tuple2[K, LongValue]) => (i.f0, i.f1))
}
/**
* Return the out-degree of all vertices in the graph
*
* @return A DataSet of Tuple2
*/
def outDegrees(): DataSet[(K, LongValue)] = {
wrap(jgraph.outDegrees).map((i: jtuple.Tuple2[K, LongValue]) => (i.f0, i.f1))
}
/**
* Return the degree of all vertices in the graph
*
* @return A DataSet of Tuple2
*/
def getDegrees(): DataSet[(K, LongValue)] = {
wrap(jgraph.getDegrees).map((i: jtuple.Tuple2[K, LongValue]) => (i.f0, i.f1))
}
/**
* This operation adds all inverse-direction edges to the graph.
*
* @return the undirected graph.
*/
def getUndirected(): Graph[K, VV, EV] = {
new Graph(jgraph.getUndirected)
}
/**
* Reverse the direction of the edges in the graph
*
* @return a new graph with all edges reversed
* @throws UnsupportedOperationException
*/
def reverse(): Graph[K, VV, EV] = {
new Graph(jgraph.reverse())
}
/**
* Compute an aggregate over the edges of each vertex. The function applied
* on the edges has access to the vertex value.
*
* @param edgesFunction the function to apply to the neighborhood
* @param direction the edge direction (in-, out-, all-)
* @tparam T the output type
* @return a dataset of a T
*/
def groupReduceOnEdges[T: TypeInformation : ClassTag](edgesFunction:
EdgesFunctionWithVertexValue[K, VV, EV,
T], direction: EdgeDirection):
DataSet[T] = {
wrap(jgraph.groupReduceOnEdges(edgesFunction, direction, createTypeInformation[T]))
}
/**
* Compute an aggregate over the edges of each vertex. The function applied
* on the edges has access to the vertex value.
*
* @param edgesFunction the function to apply to the neighborhood
* @param direction the edge direction (in-, out-, all-)
* @tparam T the output type
* @return a dataset of a T
*/
def groupReduceOnEdges[T: TypeInformation : ClassTag](edgesFunction: EdgesFunction[K, EV, T],
direction: EdgeDirection): DataSet[T] = {
wrap(jgraph.groupReduceOnEdges(edgesFunction, direction, createTypeInformation[T]))
}
/**
* Compute an aggregate over the neighbors (edges and vertices) of each
* vertex. The function applied on the neighbors has access to the vertex
* value.
*
* @param neighborsFunction the function to apply to the neighborhood
* @param direction the edge direction (in-, out-, all-)
* @tparam T the output type
* @return a dataset of a T
*/
def groupReduceOnNeighbors[T: TypeInformation : ClassTag](neighborsFunction:
NeighborsFunctionWithVertexValue[K,
VV, EV, T], direction:
EdgeDirection): DataSet[T] = {
wrap(jgraph.groupReduceOnNeighbors(neighborsFunction, direction, createTypeInformation[T]))
}
/**
* Compute an aggregate over the neighbors (edges and vertices) of each
* vertex.
*
* @param neighborsFunction the function to apply to the neighborhood
* @param direction the edge direction (in-, out-, all-)
* @tparam T the output type
* @return a dataset of a T
*/
def groupReduceOnNeighbors[T: TypeInformation : ClassTag](neighborsFunction:
NeighborsFunction[K, VV, EV, T],
direction: EdgeDirection):
DataSet[T] = {
wrap(jgraph.groupReduceOnNeighbors(neighborsFunction, direction, createTypeInformation[T]))
}
/**
* @return a long integer representing the number of vertices
*/
def numberOfVertices(): Long = {
jgraph.numberOfVertices()
}
/**
* @return a long integer representing the number of edges
*/
def numberOfEdges(): Long = {
jgraph.numberOfEdges()
}
/**
* @return The IDs of the vertices as DataSet
*/
def getVertexIds(): DataSet[K] = {
wrap(jgraph.getVertexIds)
}
/**
* @return The IDs of the edges as DataSet
*/
def getEdgeIds(): DataSet[(K, K)] = {
wrap(jgraph.getEdgeIds).map((i: jtuple.Tuple2[K, K]) => (i.f0, i.f1))
}
/**
* Adds the input vertex to the graph. If the vertex already
* exists in the graph, it will not be added again.
*
* @param vertex the vertex to be added
* @return the new graph containing the existing vertices as well as the one just added
*/
def addVertex(vertex: Vertex[K, VV]) = {
wrapGraph(jgraph.addVertex(vertex))
}
/**
* Adds the list of vertices, passed as input, to the graph.
* If the vertices already exist in the graph, they will not be added once more.
*
* @param vertices the list of vertices to add
* @return the new graph containing the existing and newly added vertices
*/
def addVertices(vertices: List[Vertex[K, VV]]): Graph[K, VV, EV] = {
wrapGraph(jgraph.addVertices(vertices.asJava))
}
/**
* Adds the given list edges to the graph.
*
* When adding an edge for a non-existing set of vertices,
* the edge is considered invalid and ignored.
*
* @param edges the data set of edges to be added
* @return a new graph containing the existing edges plus the newly added edges.
*/
def addEdges(edges: List[Edge[K, EV]]): Graph[K, VV, EV] = {
wrapGraph(jgraph.addEdges(edges.asJava))
}
/**
* Adds the given edge to the graph. If the source and target vertices do
* not exist in the graph, they will also be added.
*
* @param source the source vertex of the edge
* @param target the target vertex of the edge
* @param edgeValue the edge value
* @return the new graph containing the existing vertices and edges plus the
* newly added edge
*/
def addEdge(source: Vertex[K, VV], target: Vertex[K, VV], edgeValue: EV) = {
wrapGraph(jgraph.addEdge(source, target, edgeValue))
}
/**
* Removes the given vertex and its edges from the graph.
*
* @param vertex the vertex to remove
* @return the new graph containing the existing vertices and edges without
* the removed vertex and its edges
*/
def removeVertex(vertex: Vertex[K, VV]) = {
wrapGraph(jgraph.removeVertex(vertex))
}
/**
* Removes the given vertex and its edges from the graph.
*
* @param vertices list of vertices to remove
* @return the new graph containing the existing vertices and edges without
* the removed vertex and its edges
*/
def removeVertices(vertices: List[Vertex[K, VV]]): Graph[K, VV, EV] = {
wrapGraph(jgraph.removeVertices(vertices.asJava))
}
/**
* Removes all edges that match the given edge from the graph.
*
* @param edge the edge to remove
* @return the new graph containing the existing vertices and edges without
* the removed edges
*/
def removeEdge(edge: Edge[K, EV]) = {
wrapGraph(jgraph.removeEdge(edge))
}
/**
* Removes all the edges that match the edges in the given data set from the graph.
*
* @param edges the list of edges to be removed
* @return a new graph where the edges have been removed and in which the vertices remained intact
*/
def removeEdges(edges: List[Edge[K, EV]]): Graph[K, VV, EV] = {
wrapGraph(jgraph.removeEdges(edges.asJava))
}
/**
* Performs union on the vertices and edges sets of the input graphs
* removing duplicate vertices but maintaining duplicate edges.
*
* @param graph the graph to perform union with
* @return a new graph
*/
def union(graph: Graph[K, VV, EV]) = {
wrapGraph(jgraph.union(graph.getWrappedGraph))
}
/**
* Performs Difference on the vertex and edge sets of the input graphs
* removes common vertices and edges. If a source/target vertex is removed,
* its corresponding edge will also be removed
*
* @param graph the graph to perform difference with
* @return a new graph where the common vertices and edges have been removed
*/
def difference(graph: Graph[K, VV, EV]) = {
wrapGraph(jgraph.difference(graph.getWrappedGraph))
}
/**
* Performs intersect on the edge sets of the input graphs. Edges are considered equal, if they
* have the same source identifier, target identifier and edge value.
*
* The method computes pairs of equal edges from the input graphs. If the same edge occurs
* multiple times in the input graphs, there will be multiple edge pairs to be considered. Each
* edge instance can only be part of one pair. If the given parameter `distinctEdges` is set
* to `true`, there will be exactly one edge in the output graph representing all pairs of
* equal edges. If the parameter is set to `false`, both edges of each pair will be in the
* output.
*
* Vertices in the output graph will have no vertex values.
*
* @param graph the graph to perform intersect with
* @param distinctEdges if set to { @code true}, there will be exactly one edge in the output
* graph representing all pairs of equal edges, otherwise, for each pair,
* both edges will be in the output graph
* @return a new graph which contains only common vertices and edges from the input graphs
*/
def intersect(graph: Graph[K, VV, EV], distinctEdges: Boolean): Graph[K, NullValue, EV] = {
wrapGraph(jgraph.intersect(graph.getWrappedGraph, distinctEdges))
}
/**
* Compute a reduce transformation over the neighbors' vertex values of each vertex.
* For each vertex, the transformation consecutively calls a
* [[ReduceNeighborsFunction]] until only a single value for each vertex remains.
* The [[ReduceNeighborsFunction]] combines a pair of neighbor vertex values
* into one new value of the same type.
*
* @param reduceNeighborsFunction the reduce function to apply to the neighbors of each vertex.
* @param direction the edge direction (in-, out-, all-)
* @return a Dataset of Tuple2, with one tuple per vertex.
* The first field of the Tuple2 is the vertex ID and the second field
* is the aggregate value computed by the provided [[ReduceNeighborsFunction]].
*/
def reduceOnNeighbors(reduceNeighborsFunction: ReduceNeighborsFunction[VV], direction:
EdgeDirection): DataSet[(K, VV)] = {
wrap(jgraph.reduceOnNeighbors(reduceNeighborsFunction, direction)).map(
(i: jtuple.Tuple2[K, VV]) => (i.f0, i.f1))
}
/**
* Compute a reduce transformation over the neighbors' vertex values of each vertex.
* For each vertex, the transformation consecutively calls a
* [[ReduceNeighborsFunction]] until only a single value for each vertex remains.
* The [[ReduceNeighborsFunction]] combines a pair of neighbor vertex values
* into one new value of the same type.
*
* @param reduceEdgesFunction the reduce function to apply to the edges of each vertex.
* @param direction the edge direction (in-, out-, all-)
* @return a Dataset of Tuple2, with one tuple per vertex.
* The first field of the Tuple2 is the vertex ID and the second field
* is the aggregate value computed by the provided [[ReduceNeighborsFunction]].
*/
def reduceOnEdges(reduceEdgesFunction: ReduceEdgesFunction[EV], direction: EdgeDirection):
DataSet[(K, EV)] = {
wrap(jgraph.reduceOnEdges(reduceEdgesFunction, direction)).map(
(i: jtuple.Tuple2[K, EV]) => (i.f0, i.f1))
}
/**
* @param algorithm the algorithm to run on the Graph
* @return the result of the graph algorithm
*/
def run[T: TypeInformation : ClassTag](algorithm: GraphAlgorithm[K, VV, EV, T]):
T = {
jgraph.run(algorithm)
}
/**
* A GraphAnalytic is similar to a GraphAlgorithm but is terminal and results
* are retrieved via accumulators. A Flink program has a single point of
* execution. A GraphAnalytic defers execution to the user to allow composing
* multiple analytics and algorithms into a single program.
*
* @param analytic the analytic to run on the Graph
*/
def run[T: TypeInformation : ClassTag](analytic: GraphAnalytic[K, VV, EV, T]):
GraphAnalytic[K, VV, EV, T] = {
jgraph.run(analytic)
analytic
}
/**
* Runs a scatter-gather iteration on the graph.
* No configuration options are provided.
*
* @param scatterFunction the scatter function
* @param gatherFunction the gather function
* @param maxIterations maximum number of iterations to perform
* @return the updated Graph after the scatter-gather iteration has converged or
* after maximumNumberOfIterations.
*/
def runScatterGatherIteration[M](scatterFunction: ScatterFunction[K, VV, M, EV],
gatherFunction: SpargelGatherFunction[K, VV, M],
maxIterations: Int): Graph[K, VV, EV] = {
wrapGraph(jgraph.runScatterGatherIteration(scatterFunction, gatherFunction,
maxIterations))
}
/**
* Runs a scatter-gather iteration on the graph with configuration options.
*
* @param scatterFunction the scatter function
* @param gatherFunction the gather function
* @param maxIterations maximum number of iterations to perform
* @param parameters the iteration configuration parameters
* @return the updated Graph after the scatter-gather iteration has converged or
* after maximumNumberOfIterations.
*/
def runScatterGatherIteration[M](scatterFunction: ScatterFunction[K, VV, M, EV],
gatherFunction: SpargelGatherFunction[K, VV, M],
maxIterations: Int, parameters: ScatterGatherConfiguration):
Graph[K, VV, EV] = {
wrapGraph(jgraph.runScatterGatherIteration(scatterFunction, gatherFunction,
maxIterations, parameters))
}
/**
* Runs a Gather-Sum-Apply iteration on the graph.
* No configuration options are provided.
*
* @param gatherFunction the gather function collects information about adjacent
* vertices and edges
* @param sumFunction the sum function aggregates the gathered information
* @param applyFunction the apply function updates the vertex values with the aggregates
* @param maxIterations maximum number of iterations to perform
* @tparam M the intermediate type used between gather, sum and apply
* @return the updated Graph after the gather-sum-apply iteration has converged or
* after maximumNumberOfIterations.
*/
def runGatherSumApplyIteration[M](gatherFunction: GSAGatherFunction[VV, EV, M], sumFunction:
SumFunction[VV, EV, M], applyFunction: ApplyFunction[K, VV, M], maxIterations: Int): Graph[K,
VV, EV] = {
wrapGraph(jgraph.runGatherSumApplyIteration(gatherFunction, sumFunction, applyFunction,
maxIterations))
}
/**
* Runs a Gather-Sum-Apply iteration on the graph with configuration options.
*
* @param gatherFunction the gather function collects information about adjacent
* vertices and edges
* @param sumFunction the sum function aggregates the gathered information
* @param applyFunction the apply function updates the vertex values with the aggregates
* @param maxIterations maximum number of iterations to perform
* @param parameters the iteration configuration parameters
* @tparam M the intermediate type used between gather, sum and apply
* @return the updated Graph after the gather-sum-apply iteration has converged or
* after maximumNumberOfIterations.
*/
def runGatherSumApplyIteration[M](gatherFunction: GSAGatherFunction[VV, EV, M], sumFunction:
SumFunction[VV, EV, M], applyFunction: ApplyFunction[K, VV, M], maxIterations: Int,
parameters: GSAConfiguration): Graph[K, VV, EV] = {
wrapGraph(jgraph.runGatherSumApplyIteration(gatherFunction, sumFunction, applyFunction,
maxIterations, parameters))
}
/**
* Runs a vertex-centric iteration on the graph.
* No configuration options are provided.
*
* @param computeFunction the compute function
* @param combineFunction the optional message combiner function
* @param maxIterations maximum number of iterations to perform
* @return the updated Graph after the vertex-centric iteration has converged or
* after maximumNumberOfIterations.
*/
def runVertexCentricIteration[M](computeFunction: ComputeFunction[K, VV, EV, M],
combineFunction: MessageCombiner[K, M],
maxIterations: Int): Graph[K, VV, EV] = {
wrapGraph(jgraph.runVertexCentricIteration(computeFunction, combineFunction,
maxIterations))
}
/**
* Runs a vertex-centric iteration on the graph with configuration options.
*
* @param computeFunction the compute function
* @param combineFunction the optional message combiner function
* @param maxIterations maximum number of iterations to perform
* @param parameters the iteration configuration parameters
* @return the updated Graph after the vertex-centric iteration has converged or
* after maximumNumberOfIterations.
*/
def runVertexCentricIteration[M](computeFunction: ComputeFunction[K, VV, EV, M],
combineFunction: MessageCombiner[K, M],
maxIterations: Int, parameters: VertexCentricConfiguration):
Graph[K, VV, EV] = {
wrapGraph(jgraph.runVertexCentricIteration(computeFunction, combineFunction,
maxIterations, parameters))
}
def validate(validator: GraphValidator[K, VV, EV]): Boolean = {
jgraph.validate(validator)
}
}