def arrow_to_dynamic(graph): """Transform a :class:`Graph` object to :class:`nx.Graph`. Args: graph (:class:`Graph`): Source graph, which type should be ARROW_PROPERTY. Returns: An op of transform arrow graph to dynamic graph with necessary configurations. """ check_argument(graph.graph_type == graph_def_pb2.ARROW_PROPERTY) config = { types_pb2.GRAPH_NAME: utils.s_to_attr(graph.key), types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(graph_def_pb2.ARROW_PROPERTY), types_pb2.DST_GRAPH_TYPE: utils.graph_type_to_attr(graph_def_pb2.DYNAMIC_PROPERTY), types_pb2.OID_TYPE: utils.s_to_attr(utils.data_type_to_cpp(graph.schema.oid_type)), types_pb2.VID_TYPE: utils.s_to_attr(utils.data_type_to_cpp(graph.schema.vid_type)), types_pb2.DEFAULT_LABEL_ID: utils.i_to_attr(graph._default_label_id), } op = Operation( graph.session_id, types_pb2.TRANSFORM_GRAPH, config=config, output_types=types_pb2.GRAPH, ) return op
def flatten_arrow_property_graph(graph, v_prop, e_prop, v_prop_type, e_prop_type, oid_type=None, vid_type=None): """Flatten arrow property graph. Args: graph (:class:`nx.Graph`): A nx graph hosts an arrow property graph. v_prop (str): The vertex property id. e_prop (str): The edge property id. v_prop_type (str): Type of the node attribute. e_prop_type (str): Type of the edge attribute. oid_type (str): Type of oid. vid_type (str): Type of vid. Returns: Operation to flatten an arrow property graph. Results in a arrow flattened graph. """ config = { types_pb2.GRAPH_NAME: utils.s_to_attr(graph.key), types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(graph_def_pb2.ARROW_FLATTENED), types_pb2.DST_GRAPH_TYPE: utils.graph_type_to_attr(graph.graph_type), types_pb2.V_DATA_TYPE: utils.s_to_attr(utils.data_type_to_cpp(v_prop_type)), types_pb2.E_DATA_TYPE: utils.s_to_attr(utils.data_type_to_cpp(e_prop_type)), } if graph.graph_type == graph_def_pb2.ARROW_PROPERTY: config[types_pb2.V_PROP_KEY] = utils.s_to_attr(str(v_prop)) config[types_pb2.E_PROP_KEY] = utils.s_to_attr(str(e_prop)) config[types_pb2.OID_TYPE] = utils.s_to_attr( utils.data_type_to_cpp(oid_type)) config[types_pb2.VID_TYPE] = utils.s_to_attr( utils.data_type_to_cpp(vid_type)) else: config[types_pb2.V_PROP_KEY] = utils.s_to_attr(v_prop) config[types_pb2.E_PROP_KEY] = utils.s_to_attr(e_prop) op = Operation( graph.session_id, types_pb2.PROJECT_TO_SIMPLE, config=config, output_types=types_pb2.GRAPH, ) return op
def create_graph(session_id, graph_type, **kwargs): """Create an `CREATE_GRAPH` op, add op to default dag. Args: session_id (str): Refer to session that the graph will be create on. graph_type (:enum:`GraphType`): GraphType defined in proto.types.proto. **kwargs: additional properties respect to different `graph_type`. Returns: An op to create a graph in c++ side with necessary configurations. """ config = { types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(graph_type), } if graph_type == types_pb2.ARROW_PROPERTY: attrs = kwargs.pop("attrs", None) if attrs: for k, v in attrs.items(): if isinstance(v, attr_value_pb2.AttrValue): config[k] = v elif graph_type == types_pb2.DYNAMIC_PROPERTY: config[types_pb2.E_FILE] = utils.s_to_attr(kwargs["efile"]) config[types_pb2.V_FILE] = utils.s_to_attr(kwargs["vfile"]) config[types_pb2.DIRECTED] = utils.b_to_attr(kwargs["directed"]) else: raise RuntimeError("Not supported graph type {}".format(graph_type)) op = Operation(session_id, types_pb2.CREATE_GRAPH, config=config, output_types=types_pb2.GRAPH) return op
def add_column(graph, results, selector): """Add a column to `graph`, produce a new graph. Args: graph (:class:`Graph`): Source ArrowProperty graph. results (:class:`Context`): Results that generated by previous app querying. selector (str): Used to select a subrange of data of results, add them as one column of graph. Returns: A new graph with new columns added. """ config = { types_pb2.GRAPH_NAME: utils.s_to_attr(graph.key), types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(graph.graph_type), types_pb2.CTX_NAME: utils.s_to_attr(results.key), types_pb2.SELECTOR: utils.s_to_attr(selector), } op = Operation( graph._session_id, types_pb2.ADD_COLUMN, config=config, output_types=types_pb2.GRAPH, ) return op
def project_dynamic_property_graph(graph, v_prop, e_prop, v_prop_type, e_prop_type): """Create project graph operation for nx graph. Args: graph (:class:`nx.Graph`): A nx graph. v_prop (str): The node attribute key to project. e_prop (str): The edge attribute key to project. v_prop_type (str): Type of the node attribute. e_prop_type (str): Type of the edge attribute. Returns: Operation to project a dynamic property graph. Results in a simple graph. """ check_argument(graph.graph_type == types_pb2.DYNAMIC_PROPERTY) config = { types_pb2.GRAPH_NAME: utils.s_to_attr(graph.key), types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(types_pb2.DYNAMIC_PROJECTED), types_pb2.V_PROP_KEY: utils.s_to_attr(v_prop), types_pb2.E_PROP_KEY: utils.s_to_attr(e_prop), types_pb2.V_DATA_TYPE: utils.s_to_attr(utils.data_type_to_cpp(v_prop_type)), types_pb2.E_DATA_TYPE: utils.s_to_attr(utils.data_type_to_cpp(e_prop_type)), } op = Operation( graph.session_id, types_pb2.PROJECT_GRAPH, config=config, output_types=types_pb2.GRAPH, ) return op
def add_edges(graph, **kwargs): """Create an `ADD_EDGES` op, add op to default dag. Args: graph (:class:`Graph`): a :class:`Graph` instance. **kwargs: additional properties respect to different `graph_type`. Returns: An op to add edges to a graph in c++ side with necessary configurations. """ config = { types_pb2.GRAPH_NAME: utils.s_to_attr(graph.key), types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(graph.graph_type), } if graph.graph_type == types_pb2.ARROW_PROPERTY: attrs = kwargs.pop("attrs", None) if attrs: for k, v in attrs.items(): if isinstance(v, attr_value_pb2.AttrValue): config[k] = v else: raise ValueError(f"Not support add edges on graph type {graph.graph_type}") op = Operation( graph.session_id, types_pb2.ADD_EDGES, config=config, output_types=types_pb2.GRAPH, ) return op
def dynamic_to_arrow(graph): """Create an op to transform a :class:`nx.Graph` object to :class:`Graph`. Args: graph (:class:`Graph`): Source graph, which type should be DYNAMIC_PROPERTY Returns: An op of transform dynamic graph to arrow graph with necessary configurations. """ check_argument(graph.graph_type == graph_def_pb2.DYNAMIC_PROPERTY) oid_type = None for node in graph: if oid_type is None: oid_type = type(node) elif oid_type != type(node): raise RuntimeError( "The vertex type is not consistent {} vs {}, can not convert it to arrow graph" .format(str(oid_type), str(type(node)))) if oid_type == int or oid_type is None: oid_type = utils.data_type_to_cpp(graph_def_pb2.LONG) elif oid_type == str: oid_type = utils.data_type_to_cpp(graph_def_pb2.STRING) else: raise RuntimeError("Unsupported oid type: " + str(oid_type)) vid_type = utils.data_type_to_cpp(graph_def_pb2.ULONG) config = { types_pb2.GRAPH_NAME: utils.s_to_attr(graph.key), types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(graph_def_pb2.ARROW_PROPERTY), types_pb2.DST_GRAPH_TYPE: utils.graph_type_to_attr(graph_def_pb2.ARROW_PROPERTY), types_pb2.OID_TYPE: utils.s_to_attr(oid_type), types_pb2.VID_TYPE: utils.s_to_attr(vid_type), } op = Operation( graph.session_id, types_pb2.TRANSFORM_GRAPH, config=config, output_types=types_pb2.GRAPH, ) return op
def project_arrow_property_graph( graph, v_label_id, v_prop_id, e_label_id, e_prop_id, v_data_type, e_data_type, oid_type=None, vid_type=None, ): """Project arrow property graph to a simple graph. Args: graph (:class:`Graph`): Source graph, which type should be ARROW_PROPERTY dst_graph_key (str): The key of projected graph. v_label_id (int): Label id of vertex used to project. v_prop_id (int): Property id of vertex used to project. e_label_id (int): Label id of edge used to project. e_prop_id (int): Property id of edge used to project. Returns: An op to project `graph`, results in a simple ARROW_PROJECTED graph. """ check_argument(graph.graph_type == types_pb2.ARROW_PROPERTY) config = { types_pb2.GRAPH_NAME: utils.s_to_attr(graph.key), types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(types_pb2.ARROW_PROJECTED), types_pb2.V_LABEL_ID: utils.i_to_attr(v_label_id), types_pb2.V_PROP_ID: utils.i_to_attr(v_prop_id), types_pb2.E_LABEL_ID: utils.i_to_attr(e_label_id), types_pb2.E_PROP_ID: utils.i_to_attr(e_prop_id), types_pb2.OID_TYPE: utils.s_to_attr(oid_type), types_pb2.VID_TYPE: utils.s_to_attr(vid_type), types_pb2.V_DATA_TYPE: utils.s_to_attr(utils.data_type_to_cpp(v_data_type)), types_pb2.E_DATA_TYPE: utils.s_to_attr(utils.data_type_to_cpp(e_data_type)), } op = Operation( graph._session_id, types_pb2.PROJECT_GRAPH, config=config, output_types=types_pb2.GRAPH, ) return op
def add_labels_to_graph(graph, loader_op): """Add new labels to existed graph. Args: graph (:class:`Graph`): A graph instance. May not be fully loaded. i.e. it's in a building procedure. loader_op (:class:`graphscope.framework.operation.Operation`): Operation of loader. Raises: NotImplementedError: When encountered not supported graph type. Returns: The operation. Notes: Since we don't want to trigger the loading, we must not use any api that can trigger the loading process implicitly. """ from graphscope.framework.graph import GraphDAGNode assert isinstance(graph, GraphDAGNode) inputs = [graph.op, loader_op] # vid_type is fixed config = { types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(graph._graph_type), types_pb2.DIRECTED: utils.b_to_attr(graph._directed), types_pb2.OID_TYPE: utils.s_to_attr(graph._oid_type), types_pb2.GENERATE_EID: utils.b_to_attr(graph._generate_eid), types_pb2.VID_TYPE: utils.s_to_attr("uint64_t"), types_pb2.IS_FROM_VINEYARD_ID: utils.b_to_attr(False), } # inferred from the context of the dag. config.update({types_pb2.GRAPH_NAME: utils.place_holder_to_attr()}) if graph._graph_type != graph_def_pb2.ARROW_PROPERTY: raise NotImplementedError( f"Add vertices or edges is not supported yet on graph type {graph._graph_type}" ) op = Operation( graph._session.session_id, types_pb2.ADD_LABELS, inputs=inputs, config=config, output_types=types_pb2.GRAPH, ) return op
def project_arrow_property_graph(graph, vertex_collections, edge_collections): check_argument(graph.graph_type == graph_def_pb2.ARROW_PROPERTY) config = { types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(graph.graph_type), } config.update({ types_pb2.VERTEX_COLLECTIONS: utils.s_to_attr(vertex_collections), types_pb2.EDGE_COLLECTIONS: utils.s_to_attr(edge_collections), }) op = Operation( graph.session_id, types_pb2.PROJECT_GRAPH, config=config, inputs=[graph.op], output_types=types_pb2.GRAPH, ) return op
def create_app(graph, app): """Wrapper for create an `CREATE_APP` Operation with configuration. Compile and load an application after evaluated. Args: graph (:class:`Graph`): A :class:`Graph` instance app (:class:`App`): A :class:`App` instance. Returns: An :class:`Operation` with configuration that instruct analytical engine how to build the app. """ config = { types_pb2.APP_ALGO: utils.s_to_attr(app.algo), types_pb2.GRAPH_TYPE: utils.graph_type_to_attr(graph.graph_type), types_pb2.OID_TYPE: utils.s_to_attr(graph.schema.oid_type), types_pb2.VID_TYPE: utils.s_to_attr(graph.schema.vid_type), types_pb2.V_DATA_TYPE: utils.s_to_attr(utils.data_type_to_cpp(graph.schema.vdata_type)), types_pb2.E_DATA_TYPE: utils.s_to_attr(utils.data_type_to_cpp(graph.schema.edata_type)), types_pb2.APP_SIGNATURE: utils.s_to_attr(app.signature), types_pb2.GRAPH_SIGNATURE: utils.s_to_attr(graph.template_sigature), } if app.gar is not None: config[types_pb2.GAR] = utils.bytes_to_attr(app.gar) opr = Operation( graph.session_id, types_pb2.CREATE_APP, config=config, output_types=types_pb2.APP, ) return opr