def get_dot_string(
        self, name_and_op_style=False, annotation=False, highlight_debug_nodes=None
    ):
        """
        Return the dot string that can be used to show the whole graph
        with dot. By default, the graph contains op and type. If
        name_and_op_style is set, the graph will contain the name of the node
        and the op instead.

        * Input nodes : yellow
        * constant nodes : azure
        * output nodes : goldenrod2
        * nodes with variable shaped tensors : cyan
        * node names or op types that user wants to highlight: green

        Parameters
        ----------
        name_and_op_style: bool
            If set, graph contains only the name and the op.

        annotation: bool
        Examples
        --------
        >>> import graphviz
        >>> graphviz.Source(network.get_dot_string()).view()

        """
        if highlight_debug_nodes is None:
            highlight_debug_nodes = []
        function_names = sorted(self.functions.keys())

        dotstring = "digraph g {\n" + "\tcompound=true;\n"
        # find all tensor nodes with unknown sizes
        ctr = 0
        for k in function_names:
            const_nodes = const_determined_nodes(self.functions[k].graph)
            unknown_sized_tensor_ops = []
            for v, n in self.functions[k].graph.items():
                if n.datatype is None or (
                    n.datatype is not None
                    and types.is_tensor(n.datatype)
                    and (
                        len(n.datatype.get_shape()) == 0 or -1 in n.datatype.get_shape()
                    )
                ):
                    unknown_sized_tensor_ops.append(v)
                if n.op in highlight_debug_nodes:
                    highlight_debug_nodes.append(v)

            v = self.functions[k]
            vis = DotVisitor(annotation)
            vis.highlight_nodes(v.inputs, "yellow").highlight_nodes(
                const_nodes, "azure2"
            ).highlight_nodes(v.outputs, "goldenrod2").highlight_nodes(
                unknown_sized_tensor_ops, "cyan2"
            )
            if len(highlight_debug_nodes) > 0:
                vis.highlight_nodes(highlight_debug_nodes, "green")
            if name_and_op_style:
                vis.labeller(lambda n: n.name + " (" + n.op + ")")

            res = vis.visit_all(v.graph, nodename_prefix=str(ctr)).get_result(
                "subgraph", "cluster_" + k.replace("/", "_")
            )
            dotstring += "\n".join("\t" + r for r in res.split("\n")) + "\n"
            ctr += 1
        dotstring += "}"
        return dotstring

        Return the dot string that can be used to show the whole graph
        with dot. By default, the graph contains op and type. If
        name_and_op_style is set, the graph will contain the name of the node
        and the op instead.

        * Input nodes : yellow
        * constant nodes : azure
        * output nodes : goldenrod2
        * nodes with variable shaped tensors : cyan
        * node names or op types that user wants to highlight: green

        Parameters
        ----------
        name_and_op_style: bool
            If set, graph contains only the name and the op.

        annotation: bool
        Examples
        --------
        >>> import graphviz
        >>> graphviz.Source(network.get_dot_string()).view()

        
coremltools/converters/mil/frontend/tensorflow/tfssa.py