def to_string(self):
        """Return string representation of graph in DOT language.

        @return: graph and subelements
        @rtype: `str`
        """
        graph = list()

        if self.obj_dict.get("strict", None) is not None:
            if self == self.get_parent_graph() and self.obj_dict["strict"]:
                graph.append("strict ")

        graph_type = self.obj_dict["type"]
        if graph_type == "subgraph" and not self.obj_dict.get("show_keyword", True):
            graph_type = ""
        s = "{type} {name} {{\n".format(type=graph_type, name=self.obj_dict["name"])
        graph.append(s)

        for attr in sorted(self.obj_dict["attributes"]):
            if self.obj_dict["attributes"].get(attr, None) is not None:
                val = self.obj_dict["attributes"].get(attr)
                if val == "":
                    val = '""'
                if val is not None:
                    graph.append("%s=%s" % (attr, quote_if_necessary(val)))
                else:
                    graph.append(attr)

                graph.append(";\n")

        edges_done = set()

        edge_obj_dicts = list()
        for k in self.obj_dict["edges"]:
            edge_obj_dicts.extend(self.obj_dict["edges"][k])

        if edge_obj_dicts:
            edge_src_set, edge_dst_set = list(
                zip(*[obj["points"] for obj in edge_obj_dicts])
            )
            edge_src_set, edge_dst_set = set(edge_src_set), set(edge_dst_set)
        else:
            edge_src_set, edge_dst_set = set(), set()

        node_obj_dicts = list()
        for k in self.obj_dict["nodes"]:
            node_obj_dicts.extend(self.obj_dict["nodes"][k])

        sgraph_obj_dicts = list()
        for k in self.obj_dict["subgraphs"]:
            sgraph_obj_dicts.extend(self.obj_dict["subgraphs"][k])

        obj_list = [
            (obj["sequence"], obj)
            for obj in (edge_obj_dicts + node_obj_dicts + sgraph_obj_dicts)
        ]
        obj_list.sort(key=lambda x: x[0])

        for idx, obj in obj_list:
            if obj["type"] == "node":
                node = Node(obj_dict=obj)

                if self.obj_dict.get("suppress_disconnected", False):
                    if (
                        node.get_name() not in edge_src_set
                        and node.get_name() not in edge_dst_set
                    ):
                        continue

                graph.append(node.to_string() + "\n")

            elif obj["type"] == "edge":
                edge = Edge(obj_dict=obj)

                if self.obj_dict.get("simplify", False) and edge in edges_done:
                    continue

                graph.append(edge.to_string() + "\n")
                edges_done.add(edge)

            else:
                sgraph = Subgraph(obj_dict=obj)
                graph.append(sgraph.to_string() + "\n")

        graph.append("}\n")

        return "".join(graph)
Return string representation of graph in DOT language.

        @return: graph and subelements
        @rtype: `str`
        
python/aitemplate/utils/visualization/pydot.py