def build_graph(graph_tree, weight_fxn): # TODO: Load graph attributes # TODO: support Bipartite Graphs # What kind of graph is being built? is_bipartite = bool("bipartite" in graph_tree and graph_tree["bipartite"]) is_directed = bool("directed" in graph_tree and graph_tree["directed"]) if is_bipartite: G = BipartiteGraph() elif is_directed: G = DiGraph() else: G = Graph() # Build the nodes if "node" in graph_tree: # get the list of nodes nodes = graph_tree["node"] # ensure the node-list is a list (needed if there's only one node) if not isinstance(nodes, list): nodes = [nodes] ### Hack to make bipartite graphs work ### # We are not able to force the id of an added node, so we need # to add all the nodes first, and separately add the data to the node # having the correct id # TODO: Fixed this hack. The cause is near line 432. if is_bipartite: # find the largest U-node id: u_nodes = filter(lambda n: n["isInU"], nodes) max_u_id = max(map(lambda n: n["id"], u_nodes)) min_u_id = min(map(lambda n: n["id"], u_nodes)) # find the largest V-node id: v_nodes = filter(lambda n: not n["isInU"], nodes) max_v_id = max(map(lambda n: n["id"], v_nodes)) min_v_id = min(map(lambda n: n["id"], v_nodes)) is_max_v_bigger = max_v_id > max_u_id if is_max_v_bigger and min_v_id < max_u_id: ZenException("The U and V ids are interspersed, so a hack " "to make bipartite graphs work won't work") elif min_u_id < max_v_id: ZenException("The U and V ids are interspersed, so a hack " "to make bipartite graphs work won't work") if is_max_v_bigger: for i in range(min_u_id, max_u_id + 1): G.add_v_node() for i in range(min_v_id, max_v_id + 1): G.add_u_node() else: for i in range(min_v_id, max_v_id + 1): G.add_u_node() for i in range(min_u_id, max_u_id + 1): G.add_v_node() # Build each node and add to the graph extant_nodes = [] for node in sorted(nodes, None, lambda n: n["id"]): # Does the node have an id? has_id = True has_valid_id = True if "id" not in node: has_id = False has_valid_id = False # We can only use positive integer node ids as graph idx # If that's not the case, treat it like any other attribute elif not isinstance(node["id"], int) or node["id"] < 0: has_valid_id = False # Got a valid node id node_idx = node["id"] # this is part of the bipartite HACK extant_nodes.append(node_idx) # For bipartite graphs determine which node set this belongs to if is_bipartite: is_in_U = node["isInU"] # collect and verify all the node properties standard_keys = set(["id", "name", "zenData"]) node_data = {} node_obj = None zen_data = None for key, val in node.items(): if key == "name": node_obj = val # give preference to 'name' as source of node_obj elif key == "label" and node_obj is None: node_obj = val elif key == "zenData": zen_data = val # node_data is dict of all other attributes else: node_data[key] = val # _set_ to node_data else _append_ if zen_data is not None: if len(node_data) == 0: node_data = zen_data else: node_data["zenData"] = zen_data elif len(node_data) == 0: node_data = None # make sure that the node object is hashable otherwise put it if not isinstance(node_obj, basestring) and node_obj is not None: if not isinstance(node_obj, Hashable): if not isinstance(node_obj, Iterable): node_obj = None else: node_obj = tuple(node_obj) # For bipartite graph, this insertion method does not guarantee # that indices will be unchanged after a read-write cycle if is_bipartite: G.set_node_object_(node_idx, node_obj) G.set_node_data_(node_idx, node_data) # G.add_node_by_class(is_in_U, node_obj, node_data) elif has_id and has_valid_id: if is_directed: G.add_node_x(node_idx, G.edge_list_capacity, G.edge_list_capacity, node_obj, node_data) else: G.add_node_x(node_idx, G.edge_list_capacity, node_obj, node_data) else: if G.is_directed: G.add_node(nobj=node_obj, data=node_data) else: G.add_node(nobj=node_obj, data=node_data) # cleanup the Hacked mess if is_bipartite: for idx in G.U_(): if idx not in extant_nodes: G.rm_node_(idx) for idx in G.V_(): if idx not in extant_nodes: G.rm_node_(idx) # add edges if "edge" in graph_tree: # ensure edge list is a list (needed if there is only one edge) edges = graph_tree["edge"] if not isinstance(edges, list): edges = [edges] # iterate over the edges, add each one to the graph for edge in edges: # make sure source and target are specified source = None target = None if "source" not in edge: raise ZenException("Edge is missing the source attribute " "(edge = %s)" % str(edge)) if "target" not in edge: raise ZenException("Edge is missing the target attribute " "(edge = %s)" % str(edge)) weight = 1 edge_idx = None zen_data = None edge_data = {} for key, val in edge.items(): if key == "id": edge_idx = val if type(val) != int: raise ZenException("Edge id attribute must be a " "positive integer (edge = %s)" % str(edge)) elif key == "source": source = val if type(val) != int or val < 0: raise ZenException( "Edge source attribute must be a " "positive integer (edge = %s)" % str(edge) ) elif key == "target": target = val if type(val) != int or val < 0: raise ZenException( "Edge target attribute must be a " "positive integer (edge = %s)" % str(edge) ) elif key == "weight": weight = float(val) elif key == "zenData": zen_data = val # edge_data is dict of all other attributes else: edge_data[key] = val # give precedence to a weight-getting function if provided if weight_fxn != None: weight = weight_fxn(edge) # if zenData is only other attribute aside from those handled above # _set_ to edge_data else _append_ if zen_data is not None: if len(edge_data) == 0: edge_data = zen_data else: edge_data["zenData"] = zen_data elif len(edge_data) == 0: edge_data = None if edge_idx != None: G.add_edge_x(edge_idx, source, target, edge_data, weight) else: G.add_edge_(source, target, edge_data, weight) return G
def build_graph(graph_tree, weight_fxn): # What kind of graph is being built? is_bipartite = bool('bipartite' in graph_tree and graph_tree['bipartite']) is_directed = bool('directed' in graph_tree and graph_tree['directed']) if is_bipartite: G = BipartiteGraph() elif is_directed: G = DiGraph() else: G = Graph() # Build the nodes if 'node' in graph_tree: # get the list of nodes nodes = graph_tree['node'] # ensure the node-list is a list (needed if there's only one node) if not isinstance(nodes, list): nodes = [nodes] # Build each node and add to the graph for node in nodes: # Does the node have an id? has_id = True has_valid_id = True if 'id' not in node: has_id = False has_valid_id = False # We can only use positive integer node ids as graph idx # If that's not the case, treat it like any other attribute elif not isinstance(node['id'], int) or node['id'] < 0: has_valid_id = False # Got a valid node id node_idx = node['id'] # For bipartite graphs determine which node set this belongs to if is_bipartite: is_in_U = node['isInU'] # collect and verify all the node properties standard_keys = set(['id', 'name', 'zenData']) node_data = {} node_obj = None zen_data = None for key, val in list(node.items()): if key == 'name': node_obj = val # give preference to 'name' as source of node_obj elif key == 'label' and node_obj is None: node_obj = val elif key == 'zenData': zen_data = val # node_data is dict of all other attributes else: node_data[key] = val # _set_ to node_data else _append_ if zen_data is not None: if len(node_data) == 0: node_data = zen_data else: node_data['zenData'] = zen_data elif len(node_data) == 0: node_data = None # make sure that the node object is hashable otherwise put it if not isinstance(node_obj, str) and node_obj is not None: if not isinstance(node_obj, Hashable): \ if not isinstance(node_obj, Iterable): node_obj = None else: node_obj = tuple(node_obj) # For bipartite graph, this insertion method does not guarantee # that indices will be unchanged after a read-write cycle if is_bipartite: G.add_node_by_class(is_in_U, node_obj, node_data) elif has_id and has_valid_id: if is_directed: G.add_node_x(node_idx, G.edge_list_capacity, G.edge_list_capacity, node_obj, node_data) else: G.add_node_x(node_idx, G.edge_list_capacity, node_obj, node_data) else: if G.is_directed: G.add_node(nobj=node_obj, data=node_data) else: G.add_node(nobj=node_obj, data=node_data) # add edges if 'edge' in graph_tree: # ensure edge list is a list (needed if there is only one edge) edges = graph_tree['edge'] if not isinstance(edges, list): edges = [edges] # iterate over the edges, add each one to the graph for edge in edges: # make sure source and target are specified source = None target = None if 'source' not in edge: raise ZenException('Edge is missing the source attribute ' '(edge = %s)' % str(edge)) if 'target' not in edge: raise ZenException('Edge is missing the target attribute ' '(edge = %s)' % str(edge)) weight = 1 edge_idx = None zen_data = None edge_data = {} for key, val in list(edge.items()): if key == 'id': edge_idx = val if type(val) != int: raise ZenException('Edge id attribute must be a ' 'positive integer (edge = %s)' % str(edge)) elif key == 'source': source = val if type(val) != int or val < 0: raise ZenException('Edge source attribute must be a ' 'positive integer (edge = %s)' % str(edge)) elif key == 'target': target = val if type(val) != int or val < 0: raise ZenException('Edge target attribute must be a ' 'positive integer (edge = %s)' % str(edge)) elif key == 'weight': weight = float(val) elif key == 'zenData': zen_data = val # edge_data is dict of all other attributes else: edge_data[key] = val # give precedence to a weight-getting function if provided if weight_fxn != None: weight = weight_fxn(edge) # if zenData is only other attribute aside from those handled above # _set_ to edge_data else _append_ if zen_data is not None: if len(edge_data) == 0: edge_data = zen_data else: edge_data['zenData'] = zen_data elif len(edge_data) == 0: edge_data = None if edge_idx != None: G.add_edge_x(edge_idx, source, target, edge_data, weight) else: G.add_edge_(source, target, edge_data, weight) return G
def build_graph(graph_tree, weight_fxn): # What kind of graph is being built? is_bipartite = bool('bipartite' in graph_tree and graph_tree['bipartite']) is_directed = bool('directed' in graph_tree and graph_tree['directed']) if is_bipartite: G = BipartiteGraph() elif is_directed: G = DiGraph() else: G = Graph() # Build the nodes if 'node' in graph_tree: # get the list of nodes nodes = graph_tree['node'] # ensure the node-list is a list (needed if there's only one node) if not isinstance(nodes, list): nodes = [ nodes ] # Build each node and add to the graph for node in nodes: # Does the node have an id? has_id = True has_valid_id = True if 'id' not in node: has_id = False has_valid_id = False # We can only use positive integer node ids as graph idx # If that's not the case, treat it like any other attribute elif not isinstance(node['id'], int) or node['id'] < 0: has_valid_id = False # Got a valid node id node_idx = node['id'] # For bipartite graphs determine which node set this belongs to if is_bipartite: is_in_U = node['isInU'] # collect and verify all the node properties standard_keys = set(['id', 'name', 'zenData']) node_data = {} node_obj = None zen_data = None for key, val in node.items(): if key == 'name': node_obj = val # give preference to 'name' as source of node_obj elif key == 'label' and node_obj is None: node_obj = val elif key == 'zenData': zen_data = val # node_data is dict of all other attributes else: node_data[key] = val # _set_ to node_data else _append_ if zen_data is not None: if len(node_data) == 0: node_data = zen_data else: node_data['zenData'] = zen_data elif len(node_data) == 0: node_data = None # make sure that the node object is hashable otherwise put it if not isinstance(node_obj, basestring) and node_obj is not None: if not isinstance(node_obj, Hashable):\ if not isinstance(node_obj, Iterable): node_obj = None else: node_obj = tuple(node_obj) # For bipartite graph, this insertion method does not guarantee # that indices will be unchanged after a read-write cycle if is_bipartite: G.add_node_by_class(is_in_U, node_obj, node_data) elif has_id and has_valid_id: if is_directed: G.add_node_x(node_idx, G.edge_list_capacity, G.edge_list_capacity, node_obj,node_data) else: G.add_node_x(node_idx, G.edge_list_capacity, node_obj, node_data) else: if G.is_directed: G.add_node(nobj=node_obj, data=node_data) else: G.add_node(nobj=node_obj, data=node_data) # add edges if 'edge' in graph_tree: # ensure edge list is a list (needed if there is only one edge) edges = graph_tree['edge'] if not isinstance(edges, list): edges = [ edges ] # iterate over the edges, add each one to the graph for edge in edges: # make sure source and target are specified source = None target = None if 'source' not in edge: raise ZenException('Edge is missing the source attribute '\ '(edge = %s)' % str(edge)) if 'target' not in edge: raise ZenException('Edge is missing the target attribute '\ '(edge = %s)' % str(edge)) weight = 1 edge_idx = None zen_data = None edge_data = {} for key, val in edge.items(): if key == 'id': edge_idx = val if type(val) != int: raise ZenException('Edge id attribute must be a '\ 'positive integer (edge = %s)' % str(edge)) elif key == 'source': source = val if type(val) != int or val < 0: raise ZenException('Edge source attribute must be a '\ 'positive integer (edge = %s)' % str(edge)) elif key == 'target': target = val if type(val) != int or val < 0: raise ZenException('Edge target attribute must be a '\ 'positive integer (edge = %s)' % str(edge)) elif key == 'weight': weight = float(val) elif key == 'zenData': zen_data = val # edge_data is dict of all other attributes else: edge_data[key] = val # give precedence to a weight-getting function if provided if weight_fxn != None: weight = weight_fxn(edge) # if zenData is only other attribute aside from those handled above # _set_ to edge_data else _append_ if zen_data is not None: if len(edge_data) == 0: edge_data = zen_data else: edge_data['zenData'] = zen_data elif len(edge_data) == 0: edge_data = None; if edge_idx != None: G.add_edge_x(edge_idx,source,target,edge_data,weight) else: G.add_edge_(source,target,edge_data,weight) return G