|  | 
| 297 | 297 |     :meth:`~GenericGraph.show3d` | Plot the graph using :class:`~sage.plot.plot3d.tachyon.Tachyon`, and shows the resulting plot. | 
| 298 | 298 |     :meth:`~GenericGraph.graphviz_string` | Return a representation in the ``dot`` language. | 
| 299 | 299 |     :meth:`~GenericGraph.graphviz_to_file_named` | Write a representation in the ``dot`` language in a file. | 
|  | 300 | +    :meth:`~GenericGraph.tikz` | Return a :class:`~sage.misc.latex_standalone.TikzPicture` object representing the (di)graph. | 
| 300 | 301 | 
 | 
| 301 | 302 | **Algorithmically hard stuff:** | 
| 302 | 303 | 
 | 
| @@ -939,6 +940,190 @@ def _latex_(self): | 
| 939 | 940 | 
 | 
| 940 | 941 |         return self.latex_options().latex() | 
| 941 | 942 | 
 | 
|  | 943 | +    def tikz(self, format='dot2tex', edge_labels=None, | 
|  | 944 | +            color_by_label=False, prog='dot', rankdir='down', | 
|  | 945 | +            standalone_config=None, usepackage=None, | 
|  | 946 | +            usetikzlibrary=None, macros=None, | 
|  | 947 | +            use_sage_preamble=None, **kwds): | 
|  | 948 | +        r""" | 
|  | 949 | +        Return a TikzPicture of the graph. | 
|  | 950 | + | 
|  | 951 | +        If graphviz and dot2tex are available, it uses these packages for | 
|  | 952 | +        placements of vertices and edges. | 
|  | 953 | + | 
|  | 954 | +        INPUT: | 
|  | 955 | + | 
|  | 956 | +        - ``format`` -- string (default: ``None``), ``'dot2tex'`` or | 
|  | 957 | +          ``'tkz_graph'``. If ``None``, it is set to ``'dot2tex'`` if | 
|  | 958 | +          dot2tex is present, otherwise it is set to ``'tkz_graph'``. | 
|  | 959 | +        - ``edge_labels`` -- bool (default: ``None``), if ``None`` | 
|  | 960 | +          it is set to ``True`` if and only if format is ``'dot2tex'`` | 
|  | 961 | +        - ``color_by_label`` -- boolean or dictionary or function (default: | 
|  | 962 | +          ``False``); whether to color each edge with a different color | 
|  | 963 | +          according to its label; the colors are chosen along a rainbow, unless | 
|  | 964 | +          they are specified by a function or dictionary mapping labels to | 
|  | 965 | +          colors; | 
|  | 966 | + | 
|  | 967 | +        When using format ``'dot2tex'``, the following inputs are considered: | 
|  | 968 | + | 
|  | 969 | +        - ``prog`` -- string (default: ``'dot'``) the program used for the | 
|  | 970 | +          layout corresponding to one of the software of the graphviz | 
|  | 971 | +          suite: 'dot', 'neato', 'twopi', 'circo' or 'fdp'. | 
|  | 972 | +        - ``rankdir`` -- string (default: ``'down'``), direction of graph layout | 
|  | 973 | +          when prog is ``'dot'``, possible values are  ``'down'``, | 
|  | 974 | +          ``'up'``, ``'right'`` and ``'left'``. | 
|  | 975 | +        - ``subgraph_clusters`` -- (default: ``[]``) a list of lists of | 
|  | 976 | +          vertices, if supported by the layout engine, nodes belonging to | 
|  | 977 | +          the same cluster subgraph are drawn together, with the entire | 
|  | 978 | +          drawing of the cluster contained within a bounding rectangle. | 
|  | 979 | + | 
|  | 980 | +        Additionnal keywords arguments are forwarded to | 
|  | 981 | +        :meth:`sage.graphs.graph_latex.GraphLatex.set_option`. | 
|  | 982 | + | 
|  | 983 | +        The following inputs define the preamble of the latex standalone | 
|  | 984 | +        document class file containing the tikzpicture: | 
|  | 985 | + | 
|  | 986 | +        - ``standalone_config`` -- list of strings (default: ``["border=4mm"]``); | 
|  | 987 | +          latex document class standalone configuration options | 
|  | 988 | +        - ``usepackage`` -- list of strings (default: ``[]``); latex | 
|  | 989 | +          packages | 
|  | 990 | +        - ``usetikzlibrary`` -- list of strings (default: ``[]``); tikz | 
|  | 991 | +          libraries to use | 
|  | 992 | +        - ``macros`` -- list of strings (default: ``[]``); list of | 
|  | 993 | +          newcommands needed for the picture | 
|  | 994 | +        - ``use_sage_preamble`` -- bool (default: ``None``), if ``None`` | 
|  | 995 | +          it is set to ``True`` if and only if format is ``'tkz_graph'`` | 
|  | 996 | + | 
|  | 997 | +        OUTPUT: | 
|  | 998 | + | 
|  | 999 | +        An instance of :mod:`sage.misc.latex_standalone.TikzPicture`. | 
|  | 1000 | + | 
|  | 1001 | +        .. NOTE:: | 
|  | 1002 | + | 
|  | 1003 | +            Prerequisite: dot2tex optional Sage package and graphviz must be | 
|  | 1004 | +            installed when using format ``'dot2tex'``. | 
|  | 1005 | + | 
|  | 1006 | +        EXAMPLES:: | 
|  | 1007 | + | 
|  | 1008 | +            sage: g = graphs.PetersenGraph() | 
|  | 1009 | +            sage: tikz = g.tikz()                   # optional - dot2tex graphviz        # long time | 
|  | 1010 | +            sage: _ = tikz.pdf(view=False)          # optional - dot2tex graphviz latex  # long time | 
|  | 1011 | + | 
|  | 1012 | +        :: | 
|  | 1013 | + | 
|  | 1014 | +            sage: tikz = g.tikz(format='tkz_graph') | 
|  | 1015 | +            sage: _ = tikz.pdf(view=False)          # optional - latex | 
|  | 1016 | + | 
|  | 1017 | +        Using another value for ``prog``:: | 
|  | 1018 | + | 
|  | 1019 | +            sage: tikz = g.tikz(prog='neato')       # optional - dot2tex graphviz        # long time | 
|  | 1020 | +            sage: _ = tikz.pdf()                    # optional - dot2tex graphviz latex  # long time | 
|  | 1021 | + | 
|  | 1022 | +        Using ``color_by_label`` with default rainbow colors:: | 
|  | 1023 | + | 
|  | 1024 | +            sage: G = DiGraph({0: {1: 333, 2: 444}, 1: {0: 444}, 2: {0: 555}}) | 
|  | 1025 | +            sage: t = G.tikz(color_by_label=True)   # optional - dot2tex graphviz        # long time | 
|  | 1026 | +            sage: _ = t.pdf(view=False)             # optional - dot2tex graphviz latex  # long time | 
|  | 1027 | + | 
|  | 1028 | +        Using ``color_by_label`` with colors given as a dictionary:: | 
|  | 1029 | + | 
|  | 1030 | +            sage: G = DiGraph({0: {1: 333, 2: 444}, 1: {0: 444}, 2: {0: 555}}) | 
|  | 1031 | +            sage: cbl = {333:'orange', 444: 'yellow', 555: 'purple'} | 
|  | 1032 | +            sage: t = G.tikz(color_by_label=cbl)    # optional - dot2tex graphviz        # long time | 
|  | 1033 | +            sage: _ = t.pdf(view=False)             # optional - dot2tex graphviz latex  # long time | 
|  | 1034 | + | 
|  | 1035 | +        Using ``color_by_label`` with colors given as a function:: | 
|  | 1036 | + | 
|  | 1037 | +            sage: G = DiGraph({0: {1: -333, 2: -444}, 1: {0: 444}, 2: {0: 555}}) | 
|  | 1038 | +            sage: cbl = lambda label:'green' if label >= 0 else 'orange' | 
|  | 1039 | +            sage: t = G.tikz(color_by_label=cbl)    # optional - dot2tex graphviz        # long time | 
|  | 1040 | +            sage: _ = t.pdf(view=False)             # optional - dot2tex graphviz latex  # long time | 
|  | 1041 | + | 
|  | 1042 | +        Using another value for ``rankdir``:: | 
|  | 1043 | + | 
|  | 1044 | +            sage: tikz = g.tikz(rankdir='right')    # optional - dot2tex graphviz       # long time | 
|  | 1045 | +            sage: _ = tikz.pdf(view=False)          # optional - dot2tex graphviz latex # long time | 
|  | 1046 | + | 
|  | 1047 | +        Using subgraphs clusters (broken when using labels, see | 
|  | 1048 | +        :issue:`22070`):: | 
|  | 1049 | + | 
|  | 1050 | +            sage: S = FiniteSetMaps(5) | 
|  | 1051 | +            sage: I = S((0,1,2,3,4)) | 
|  | 1052 | +            sage: a = S((0,1,3,0,0)) | 
|  | 1053 | +            sage: b = S((0,2,4,1,0)) | 
|  | 1054 | +            sage: roots = [I] | 
|  | 1055 | +            sage: succ = lambda v: [v*a,v*b,a*v,b*v] | 
|  | 1056 | +            sage: R = RecursivelyEnumeratedSet(roots, succ) | 
|  | 1057 | +            sage: G = R.to_digraph() | 
|  | 1058 | +            sage: G | 
|  | 1059 | +            Looped multi-digraph on 27 vertices | 
|  | 1060 | +            sage: C = G.strongly_connected_components() | 
|  | 1061 | +            sage: tikz = G.tikz(subgraph_clusters=C)# optional - dot2tex graphviz       # long time | 
|  | 1062 | +            sage: tikz.add_usepackage('amstext')    # optional - dot2tex graphviz       # long time | 
|  | 1063 | +            sage: _ = tikz.pdf(view=False)          # optional - dot2tex graphviz latex # long time | 
|  | 1064 | + | 
|  | 1065 | +        An example coming from ``graphviz_string`` documentation in SageMath:: | 
|  | 1066 | + | 
|  | 1067 | +            sage: # needs sage.symbolic | 
|  | 1068 | +            sage: f(x) = -1 / x | 
|  | 1069 | +            sage: g(x) = 1 / (x + 1) | 
|  | 1070 | +            sage: G = DiGraph() | 
|  | 1071 | +            sage: G.add_edges((i, f(i), f) for i in (1, 2, 1/2, 1/4)) | 
|  | 1072 | +            sage: G.add_edges((i, g(i), g) for i in (1, 2, 1/2, 1/4)) | 
|  | 1073 | +            sage: tikz = G.tikz(format='dot2tex')   # optional - dot2tex graphviz       # long time | 
|  | 1074 | +            sage: _ = tikz.pdf(view=False)          # optional - dot2tex graphviz latex # long time | 
|  | 1075 | +            sage: def edge_options(data): | 
|  | 1076 | +            ....:     u, v, label = data | 
|  | 1077 | +            ....:     options = {"color": {f: "red", g: "blue"}[label]} | 
|  | 1078 | +            ....:     if (u,v) == (1/2, -2): options["label"]       = "coucou"; options["label_style"] = "string" | 
|  | 1079 | +            ....:     if (u,v) == (1/2,2/3): options["dot"]         = "x=1,y=2" | 
|  | 1080 | +            ....:     if (u,v) == (1,   -1): options["label_style"] = "latex" | 
|  | 1081 | +            ....:     if (u,v) == (1,  1/2): options["dir"]         = "back" | 
|  | 1082 | +            ....:     return options | 
|  | 1083 | +            sage: tikz = G.tikz(format='dot2tex',   # optional - dot2tex graphviz       # long time | 
|  | 1084 | +            ....:               edge_options=edge_options) | 
|  | 1085 | +            sage: _ = tikz.pdf(view=False)          # optional - dot2tex graphviz latex # long time | 
|  | 1086 | +        """ | 
|  | 1087 | +        # use format dot2tex by default | 
|  | 1088 | +        if format is None: | 
|  | 1089 | +            from sage.features import PythonModule | 
|  | 1090 | +            if PythonModule("dot2tex").is_present(): | 
|  | 1091 | +                format = 'dot2tex' | 
|  | 1092 | +            else: | 
|  | 1093 | +                format = 'tkz_graph' | 
|  | 1094 | + | 
|  | 1095 | +        # by default draw edge_labels for dot2tex but not for tkz_graph | 
|  | 1096 | +        # (because tkz_graph draws None everywhere which is ugly, whereas | 
|  | 1097 | +        # dot2tex ignores the labels when they are ``None``) | 
|  | 1098 | +        if edge_labels is None: | 
|  | 1099 | +            if format == 'tkz_graph': | 
|  | 1100 | +                edge_labels = False | 
|  | 1101 | +            elif format == 'dot2tex': | 
|  | 1102 | +                edge_labels = True | 
|  | 1103 | + | 
|  | 1104 | +        self.latex_options().set_options(format=format, | 
|  | 1105 | +                edge_labels=edge_labels, color_by_label=color_by_label, | 
|  | 1106 | +                prog=prog, rankdir=rankdir, **kwds) | 
|  | 1107 | + | 
|  | 1108 | +        # by default use sage preamble only for format tkz_graph | 
|  | 1109 | +        # because content generated by tkz_graph depends on it | 
|  | 1110 | +        if use_sage_preamble is None: | 
|  | 1111 | +            if format == 'tkz_graph': | 
|  | 1112 | +                use_sage_preamble = True | 
|  | 1113 | +            elif format == 'dot2tex': | 
|  | 1114 | +                use_sage_preamble = False | 
|  | 1115 | + | 
|  | 1116 | +        if standalone_config is None: | 
|  | 1117 | +            standalone_config = ["border=4mm"] | 
|  | 1118 | + | 
|  | 1119 | +        from sage.misc.latex_standalone import TikzPicture | 
|  | 1120 | +        return TikzPicture(self._latex_(), | 
|  | 1121 | +                           standalone_config=standalone_config, | 
|  | 1122 | +                           usepackage=usepackage, | 
|  | 1123 | +                           usetikzlibrary=usetikzlibrary, | 
|  | 1124 | +                           macros=macros, | 
|  | 1125 | +                           use_sage_preamble=use_sage_preamble) | 
|  | 1126 | + | 
| 942 | 1127 |     def _matrix_(self, R=None, vertices=None): | 
| 943 | 1128 |         """ | 
| 944 | 1129 |         Return the adjacency matrix of the graph over the specified ring. | 
|  | 
0 commit comments