예제 #1
0
파일: gml.py 프로젝트: enewe101/zenlib
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
예제 #2
0
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
예제 #3
0
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