
    ljI                       U d Z ddlmZ ddgZddlZddlmZmZm	Z	 ddl
m
Z
 ddlmZmZmZmZmZ ddlZddlZer<dd	lmZ dd
lmZ ddlmZmZ ej        j        j        ej        j        j        z  Z de!d<   ddl"m#Z# ddl$m%Z%m&Z& ddl'm(Z(m)Z) ddl*m+Z+ ddl,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6 ddl7m8Z8  G d de          Z9	 	 dBdCd$Z:dDdEd%Z;	 	 	 	 dFdGd/Z<ed0         Z= ee9ej>        j?                   ee9ej>        j@                   ee9e:           ee9ej>        jA                   ee9e;           ee9ej>        jB                   ee9ej>        jC                   ee9ej>        jD                   ee9ej>        jE                   ee9e<          d0
ZFd1e!d2<   	 	 	 dHdId<ZG G d= d>e6e0?          ZH G d@ deH          Z G dA deH          ZdS )JzRMobjects used to represent mathematical graphs (think graph theory, not plotting).    )annotationsGraphDiGraphN)HashableIterableSequencecopy)TYPE_CHECKINGAnyLiteralProtocolcast)	TypeAlias)Scene)Point3DPoint3DLiker   NxGraph)AnimationGroup)CreateUncreate)Dot
LabeledDot)Line)Mobjectoverride_animate)ConvertToOpenGL)OpenGLMobjectMathTex)VMobject)BLACKc                      e Zd ZdZ	 dddZdS )LayoutFunctiona  A protocol for automatic layout functions that compute a layout for a graph to be used in :meth:`~.Graph.change_layout`.

    .. note:: The layout function must be a pure function, i.e., it must not modify the graph passed to it.

    Examples
    --------

    Here is an example that arranges nodes in an n x m grid in sorted order.

    .. manim:: CustomLayoutExample
        :save_last_frame:

        class CustomLayoutExample(Scene):
            def construct(self):
                import numpy as np
                import networkx as nx

                # create custom layout
                def custom_layout(
                    graph: nx.Graph,
                    scale: float | tuple[float, float, float] = 2,
                    n: int | None = None,
                    *args: Any,
                    **kwargs: Any,
                ):
                    nodes = sorted(list(graph))
                    height = len(nodes) // n
                    return {
                        node: (scale * np.array([
                            (i % n) - (n-1)/2,
                            -(i // n) + height/2,
                            0
                        ])) for i, node in enumerate(graph)
                    }

                # draw graph
                n = 4
                graph = Graph(
                    [i for i in range(4 * 2 - 1)],
                    [(0, 1), (0, 4), (1, 2), (1, 5), (2, 3), (2, 6), (4, 5), (5, 6)],
                    labels=True,
                    layout=custom_layout,
                    layout_config={'n': n}
                )
                self.add(graph)

    Several automatic layouts are provided by manim, and can be used by passing their name as the ``layout`` parameter to :meth:`~.Graph.change_layout`.
    Alternatively, a custom layout function can be passed to :meth:`~.Graph.change_layout` as the ``layout`` parameter. Such a function must adhere to the :class:`~.LayoutFunction` protocol.

    The :class:`~.LayoutFunction` s provided by manim are illustrated below:

    - Circular Layout: places the vertices on a circle

    .. manim:: CircularLayout
        :save_last_frame:

        class CircularLayout(Scene):
            def construct(self):
                graph = Graph(
                    [1, 2, 3, 4, 5, 6],
                    [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)],
                    layout="circular",
                    labels=True
                )
                self.add(graph)

    - Kamada Kawai Layout: tries to place the vertices such that the given distances between them are respected

    .. manim:: KamadaKawaiLayout
        :save_last_frame:

        class KamadaKawaiLayout(Scene):
            def construct(self):
                from collections import defaultdict
                distances: dict[int, dict[int, float]] = defaultdict(dict)

                # set desired distances
                distances[1][2] = 1  # distance between vertices 1 and 2 is 1
                distances[2][3] = 1  # distance between vertices 2 and 3 is 1
                distances[3][4] = 2  # etc
                distances[4][5] = 3
                distances[5][6] = 5
                distances[6][1] = 8

                graph = Graph(
                    [1, 2, 3, 4, 5, 6],
                    [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1)],
                    layout="kamada_kawai",
                    layout_config={"dist": distances},
                    layout_scale=4,
                    labels=True
                )
                self.add(graph)

    - Partite Layout: places vertices into distinct partitions

    .. manim:: PartiteLayout
        :save_last_frame:

        class PartiteLayout(Scene):
            def construct(self):
                graph = Graph(
                    [1, 2, 3, 4, 5, 6],
                    [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)],
                    layout="partite",
                    layout_config={"partitions": [[1,2],[3,4],[5,6]]},
                    labels=True
                )
                self.add(graph)

    - Planar Layout: places vertices such that edges do not cross

    .. manim:: PlanarLayout
        :save_last_frame:

        class PlanarLayout(Scene):
            def construct(self):
                graph = Graph(
                    [1, 2, 3, 4, 5, 6],
                    [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)],
                    layout="planar",
                    layout_scale=4,
                    labels=True
                )
                self.add(graph)

    - Random Layout: randomly places vertices

    .. manim:: RandomLayout
        :save_last_frame:

        class RandomLayout(Scene):
            def construct(self):
                graph = Graph(
                    [1, 2, 3, 4, 5, 6],
                    [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)],
                    layout="random",
                    labels=True
                )
                self.add(graph)

    - Shell Layout: places vertices in concentric circles

    .. manim:: ShellLayout
        :save_last_frame:

        class ShellLayout(Scene):
            def construct(self):
                nlist = [[1, 2, 3], [4, 5, 6, 7, 8, 9]]
                graph = Graph(
                    [1, 2, 3, 4, 5, 6, 7, 8, 9],
                    [(1, 2), (2, 3), (3, 1), (4, 1), (4, 2), (5, 2), (6, 2), (6, 3), (7, 3), (8, 3), (8, 1), (9, 1)],
                    layout="shell",
                    layout_config={"nlist": nlist},
                    labels=True
                )
                self.add(graph)

    - Spectral Layout: places vertices using the eigenvectors of the graph Laplacian (clusters nodes which are an approximation of the ratio cut)

    .. manim:: SpectralLayout
        :save_last_frame:

        class SpectralLayout(Scene):
            def construct(self):
                graph = Graph(
                    [1, 2, 3, 4, 5, 6],
                    [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)],
                    layout="spectral",
                    labels=True
                )
                self.add(graph)

    - Sprial Layout: places vertices in a spiraling pattern

    .. manim:: SpiralLayout
        :save_last_frame:

        class SpiralLayout(Scene):
            def construct(self):
                graph = Graph(
                    [1, 2, 3, 4, 5, 6],
                    [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)],
                    layout="spiral",
                    labels=True
                )
                self.add(graph)

    - Spring Layout: places nodes according to the Fruchterman-Reingold force-directed algorithm (attempts to minimize edge length while maximizing node separation)

    .. manim:: SpringLayout
        :save_last_frame:

        class SpringLayout(Scene):
            def construct(self):
                graph = Graph(
                    [1, 2, 3, 4, 5, 6],
                    [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (5, 1), (1, 3), (3, 5)],
                    layout="spring",
                    labels=True
                )
                self.add(graph)

    - Tree Layout: places vertices into a tree with a root node and branches (can only be used with legal trees)

    .. manim:: TreeLayout
        :save_last_frame:

        class TreeLayout(Scene):
            def construct(self):
                graph = Graph(
                    [1, 2, 3, 4, 5, 6, 7],
                    [(1, 2), (1, 3), (2, 4), (2, 5), (3, 6), (3, 7)],
                    layout="tree",
                    layout_config={"root_vertex": 1},
                    labels=True
                )
                self.add(graph)

       graphr   scale"float | tuple[float, float, float]argsr   kwargsreturndict[Hashable, Point3D]c                    dS )a  Given a graph and a scale, return a dictionary of coordinates.

        Parameters
        ----------
        graph
            The underlying NetworkX graph to be laid out. DO NOT MODIFY.
        scale
            Either a single float value, or a tuple of three float values specifying the scale along each axis.

        Returns
        -------
        dict[Hashable, Point3D]
            A dictionary mapping vertices to their positions.
        N )selfr&   r'   r)   r*   s        N/home/agentuser/manim-venv/lib/python3.11/site-packages/manim/mobject/graph.py__call__zLayoutFunction.__call__  s	    * 	    Nr%   )
r&   r   r'   r(   r)   r   r*   r   r+   r,   )__name__
__module____qualname____doc__r1   r.   r2   r0   r$   r$   &   s?        [ [@ 56      r2   r$   r%   nx_graphr'   float
partitions#Sequence[Sequence[Hashable]] | Noner*   r   r+   r,   c                ~   |t          |          dk    rt          d          t          |          }t          |          D ]9}||         D ].}| j        |         t          d          || j        |         d<   /:| j        D ]!}d| j        |         vr|| j        |         d<   "t	          j        j        | fd|i|S )Nr   zYThe partite layout requires partitions parameter to contain the partition of the verticesz:The partition must contain arrays of vertices in the graphsubsetr'   )len
ValueErrorrangenodesnxlayoutmultipartite_layout)r8   r'   r:   r*   partition_countivs          r0   _partite_layoutrH     s     S__11g
 
 	
 *ooO?## , ,A 	, 	,A~a ( P   +,HN1h''	, ^ : :8>!,,,*9HN1h'9(III&IIIr2   c                    t          j        j        | fi |}|                                D ]'\  }}d|z  |t	          j        ddg          z
  z  ||<   (d |                                D             S )Nr%   g      ?c                B    i | ]\  }}|t          j        |d g          S r   npappend.0krG   s      r0   
<dictcomp>z"_random_layout.<locals>.<dictcomp><  s,    AAATQAryQC  AAAr2   )rB   rC   random_layoutitemsrM   array)r8   r'   r*   auto_layoutrQ   rG   s         r0   _random_layoutrW   6  s     ))(==f==K!!## @ @1Ua"(C:*>*>&>?AAA[->->-@-@AAAAr2   downTroot_vertexHashable | Nonefloat | tuple | Nonevertex_spacingtuple | Noneorientationstrc                   !" |t          d          t          j        |           st          d          |t          |                     |                    it          |                                                   g}|g}t                              |         |          }i  dgt          |           z  |dk    rdnd} fd}	|rX|d         }
|
s|	                                }|	                                 |         }|t          |          z  }|s|         }||f |<   n^t           fd|D                       t          t          |                    z  }||f |<   |         }||k     r |	|||z
             |}|dz   |<   |
	                                }||         !!fd	t          |                     |                    D             }|D ]}|||<   t          |          |<   |                    |           |                    |           |Xt                                           d
           d         }t                                           d           d         }t                                           d           d         }t                                           d           d         }t!          j        ||z   ||z   dg          dz  ||z
  }||z
  }|t%          |t          t&          f          r#|dk    s|dk    rd|z  t          ||          z  "nt%          |t(                    rT|d         |dk    rd|d         z  |z  nd}|d         |dk    rd|d         z  |z  nd}t!          j        ||dg          "nd"n|\  }}t!          j        ||dg          ""fd                                 D             S )Nz2The tree layout requires the root_vertex parameterz'The tree layout must be used with treesg        rX      c                    | g}|rKg }|D ]@}	|         \  }}||z  }t          |dz   |                   |<   ||f	|<   ||         z  }A|}|IdS dS )z
        Shift the vertex v and its descendants to the right by dx.
        Precondition: v and its descendents have already had their
        positions computed.
        rc   N)max)
rG   dxlevel	nextleveluxychildrenobstructionposs
          r0   slidez_tree_layout.<locals>.slideW  s      	I ) )1v1R!$QUKN!;!;AAAXa[(		E  	 	 	 	 	r2   c              3  4   K   | ]}|         d          V  dS )r   Nr.   )rP   crn   s     r0   	<genexpr>z_tree_layout.<locals>.<genexpr>s  s+      ..aAq	......r2   c                     g | ]
}|k    |S r.   r.   )rP   ri   pts     r0   
<listcomp>z _tree_layout.<locals>.<listcomp>  s    999Abar2   c                    | d         S Nr   r.   ts    r0   <lambda>z_tree_layout.<locals>.<lambda>  
    AaD r2   )keyr   c                    | d         S rw   r.   rx   s    r0   rz   z_tree_layout.<locals>.<lambda>  r{   r2   c                    | d         S Nrc   r.   rx   s    r0   rz   z_tree_layout.<locals>.<lambda>  r{   r2   c                    | d         S r   r.   rx   s    r0   rz   z_tree_layout.<locals>.<lambda>  r{   r2   r%   c                X    i | ]&\  }\  }}|t          j        ||d g          z
  z  'S rK   )rM   rU   )rP   rG   rj   rk   centersfs       r0   rR   z _tree_layout.<locals>.<dictcomp>  s=    PPPyq&1aA!Q##f,2PPPr2   )r?   rB   is_treelist	neighborsr
   dictfromkeysr>   popsumr9   rN   minvaluesre   rM   rU   
isinstanceinttuplerT   )#rY   rZ   r'   r]   r_   stackstickparentoro   Cpcprk   rj   oxry   ctrq   x_minx_maxy_miny_maxheightwidthswshsxsyr   rl   rm   rn   rt   r   s#                                @@@@@@r0   _tree_layoutr   ?  s1    MNNN:a== DBCCCT!++k":":;;<H
 (;'((--//0EME]]8K0+>>F
C%#a&&.KV##A      "  "I 			AIIKKK!BCJJA 	NAA....2.....s2ww?AA ^r66E!R!V$$$AUKNEEGGAY9999akk!nn--999 	 	AF1II2hhRQ;  B 

..111!4E

..111!4E

..111!4E

..111!4EXuu}eemQ7881<FU]FEMEeeS\** 				VaZZUS///BBu%% 	).q)=%!))U1X%%QRB*/(*>6A::U1X&&STB2r1+&&BBBBBXr2qk""PPPPPCIIKKPPPPr2   )
circularkamada_kawaipartiteplanarrandomshellspectralspiralspringtreez dict[LayoutName, LayoutFunction]_layoutsr   3nx.classes.graph.Graph | nx.classes.digraph.DiGraphrC   9LayoutName | dict[Hashable, Point3DLike] | LayoutFunctionlayout_scaler(   layout_configdict[str, Any] | Nonedict[Hashable, Point3DLike]c                   |i }t          |t                    r|S |t          v rt          |         | fd|i|}|                    d          dk    s6|t	          |                                                   j        d         dk    r|S d |                                D             S 	  t          t          |          | fd|i|S # t          $ r}t          d| d          |d }~ww xY w)Nr'   dim   r   c                B    i | ]\  }}|t          j        |d g          S rK   rL   rO   s      r0   rR   z+_determine_graph_layout.<locals>.<dictcomp>  s,    IIITQAryQC((IIIr2   zThe layout 'zV' is neither a recognized layout, a layout function,nor a vertex placement dictionary.)r   r   r   getnext__iter__shaperT   r   r$   	TypeErrorr?   )r8   rC   r   r   rV   es         r0   _determine_graph_layoutr     sF    &$ 	8		v&xUU|U}UU
 e$$))4 4 4 6 6778>qAQFFII[5F5F5H5HIIII	/4//  ,0=    	 	 	5v 5 5 5  	s   *C 
C+C&&C+c                      e Zd ZdZdedddeddedddfdQ fd ZedRd"            Z	dSd$Z
dTd*ZddeeddfdUd2ZdVd5ZddeeddfdWd6Zddeeddd7dXd:Zddeeddd7dYd;Z ee          dd<d=            Zd> Zd? Z ee          dd<d@            ZedfdZdCZeddDd[dEZ ee          dd<dF            Zd\dHZd]dIZ ee          dd<dJ            Zed^dM            Z	 	 	 	 	 d_d`dPZ xZS )aGenericGraphaE  Abstract base class for graphs (that is, a collection of vertices
    connected with edges).

    Graphs can be instantiated by passing both a list of (distinct, hashable)
    vertex names, together with list of edges (as tuples of vertex names). See
    the examples for concrete implementations of this class for details.

    .. note::

        This implementation uses updaters to make the edges move with
        the vertices.


    See also
    --------

    :class:`.Graph`
    :class:`.DiGraph`


    Parameters
    ----------

    vertices
        A list of vertices. Must be hashable elements.
    edges
        A list of edges, specified as tuples ``(u, v)`` where both ``u``
        and ``v`` are vertices.
    labels
        Controls whether or not vertices are labeled. If ``False`` (the default),
        the vertices are not labeled; if ``True`` they are labeled using their
        names (as specified in ``vertices``) via :class:`~.MathTex`. Alternatively,
        custom labels can be specified by passing a dictionary whose keys are
        the vertices, and whose values are the corresponding vertex labels
        (rendered via, e.g., :class:`~.Text` or :class:`~.Tex`).
    label_fill_color
        Sets the fill color of the default labels generated when ``labels``
        is set to ``True``. Has no effect for other values of ``labels``.
    layout
        Either one of ``"spring"`` (the default), ``"circular"``, ``"kamada_kawai"``,
        ``"planar"``, ``"random"``, ``"shell"``, ``"spectral"``, ``"spiral"``, ``"tree"``, and ``"partite"``
        for automatic vertex positioning primarily using ``networkx``
        (see `their documentation <https://networkx.org/documentation/stable/reference/drawing.html#module-networkx.drawing.layout>`_
        for more details), a dictionary specifying a coordinate (value)
        for each vertex (key) for manual positioning, or a .:class:`~.LayoutFunction` with a user-defined automatic layout.
    layout_config
        Only for automatic layouts. A dictionary whose entries
        are passed as keyword arguments to the named layout or automatic layout function
        specified via ``layout``.
        The ``tree`` layout also accepts a special parameter ``vertex_spacing``
        passed as a keyword argument inside the ``layout_config`` dictionary.
        Passing a tuple ``(space_x, space_y)`` as this argument overrides
        the value of ``layout_scale`` and ensures that vertices are arranged
        in a way such that the centers of siblings in the same layer are
        at least ``space_x`` units apart horizontally, and neighboring layers
        are spaced ``space_y`` units vertically.
    layout_scale
        The scale of automatically generated layouts: the vertices will
        be arranged such that the coordinates are located within the
        interval ``[-scale, scale]``. Some layouts accept a tuple ``(scale_x, scale_y)``
        causing the first coordinate to be in the interval ``[-scale_x, scale_x]``,
        and the second in ``[-scale_y, scale_y]``. Default: 2.
    vertex_type
        The mobject class used for displaying vertices in the scene.
    vertex_config
        Either a dictionary containing keyword arguments to be passed to
        the class specified via ``vertex_type``, or a dictionary whose keys
        are the vertices, and whose values are dictionaries containing keyword
        arguments for the mobject related to the corresponding vertex.
    vertex_mobjects
        A dictionary whose keys are the vertices, and whose values are
        mobjects to be used as vertices. Passing vertices here overrides
        all other configuration options for a vertex.
    edge_type
        The mobject class used for displaying edges in the scene.
        Must be a subclass of :class:`~.Line` for default updaters to work.
    edge_config
        Either a dictionary containing keyword arguments to be passed
        to the class specified via ``edge_type``, or a dictionary whose
        keys are the edges, and whose values are dictionaries containing
        keyword arguments for the mobject related to the corresponding edge.
    Fr   r%   NverticesSequence[Hashable]edges#Sequence[tuple[Hashable, Hashable]]labelsbool | dictlabel_fill_colorr`   rC   r   r   r(   r   dict | Nonevertex_typetype[Mobject]vertex_configvertex_mobjects	edge_typer:   r;   rZ   r[   edge_configr+   Nonec                   	 t                                                                                        }|                               |                    |           | _        t          |t                    r| _        n2t          |t                    r|rfdD              _        ni  _         j        rt          u rt          |
i }
	i 	i 	r fd	                                D             	fdD              _         _         j                                        D ]\  }}| j        |         d<    fdD              _         j                            |
                                |||||           |i }i }i }|r4|                    di           }d |                                D             }i  _        i  _        |D ]v}||v rB||                             dt+          |                     j        |<   ||          j        |<   Ht+          |           j        |<   t+          |           j        |<   w| _                             ||             j         j                                            j         j                                                                j                   d S )	Nc                4    i | ]}|t          |           S )colorr   )rP   rG   r   s     r0   rR   z)GenericGraph.__init__.<locals>.<dictcomp>O  s)    XXX!714D#E#E#EXXXr2   c                $    i | ]\  }}|v	||S r.   r.   )rP   rQ   rG   r   s      r0   rR   z)GenericGraph.__init__.<locals>.<dictcomp>^  s0     % % %A!8:K:K1:K:K:Kr2   c           	     X    i | ]&}|                     |t                              'S r.   )r   r
   )rP   rG   default_vertex_configr   s     r0   rR   z)GenericGraph.__init__.<locals>.<dictcomp>a  sA     
 
 
EFA}  D)>$?$?@@
 
 
r2   labelc           	     8    i | ]}| d i j         |         S )r.   )_vertex_config)rP   rG   r/   r   s     r0   rR   z)GenericGraph.__init__.<locals>.<dictcomp>h  s3    TTTaKKAA$*=a*@AATTTr2   )rC   r   r   r:   rZ   
tip_configc                D    i | ]\  }}t          |t                    ||S r.   )r   r   rO   s      r0   rR   z)GenericGraph.__init__.<locals>.<dictcomp>z  sC     # # #Aq!u #1# # #r2   )super__init___empty_networkx_graphadd_nodes_fromadd_edges_from_graphr   r   _labelsboolr   r   rT   r   r   r   updatechange_layoutr   _edge_config_tip_configr
   default_edge_config_populate_edge_dictaddr   r   add_updaterupdate_edges)r/   r   r   r   r   rC   r   r   r   r   r   r   r:   rZ   r   r8   rG   r   default_tip_configr   r   r   	__class__s   ``  `   ``           @r0   r   zGenericGraph.__init__3  su   " 	--//)))&&&fd## 	"!DLL%% 	" "XXXXxXXX!< 	%K3..$K" O  M " 	% % % %!.!4!4!6!6% % %!
 
 
 
 
JR
 
 
 &;"**,, 	4 	4HAu.3D"7++TTTTT8TTT_---%'!# 	 	
 	
 	
 K  	!,r!B!B# #'--//# # #  	A 	AAK&1!n&8&8 $'9":":' ' # (31~!!$$&*+=&>&> #'+,?'@'@!!$$#6   	222$-&&(())$*##%%&&*+++++r2   nx.classes.graph.Graphc                      t          d          )z8Return an empty networkx graph for the given graph type.(To be implemented in concrete subclassesNotImplementedErrorr.   r2   r0   r   z"GenericGraph._empty_networkx_graph  s     ""LMMMr2   list[tuple[Hashable, Hashable]]c                     t          d          )z4Helper method for populating the edges of the graph.r   r   r/   r   r   s      r0   r   z GenericGraph._populate_edge_dict  s     ""LMMMr2   r/   r   rG   r   r   c                    | j         |         S Nr   )r/   rG   s     r0   __getitem__zGenericGraph.__getitem__  s    }Qr2   vertexpositionPoint3DLike | Noner   r   vertex_mobject'tuple[Hashable, Point3D, dict, Mobject]c                   ||                                  nt          j        |          }|i }|| j        v rt	          d| d          |du rt          ||          }n5|| j        v r| j        |         }nt          |t          t          f          sd }t          | j                  }	|	                    |           |	}|||d<   |t          u rt          }| |di |}|                    |           ||||fS )NVertex identifier '-' is already used for a vertex in this graph.Tr   r   r.   )
get_centerrM   asarrayr   r?   r    r   r   r   r   r
   r   r   r   r   move_to)
r/   r   r   r   r   r   r   r   np_positionbase_vertex_configs
             r0   _create_vertexzGenericGraph._create_vertex  sC    "*!1DOOrz(7K7K 	  MT]""[f[[[   D==F*:;;;EEt|##L(EEEG]#;<< 	E!$"<==!!-000*%*M'"c!!(!([99=99N{+++]NCCr2   r   r   c                l   || j         v rt          d| d          | j                            |           || j        |<   d|v r|d         | j        |<   || j        |<   || j         |<   | j         |                             |           |                     | j         |                    | j         |         S )Nr  r  r   )	r   r?   r   add_node_layoutr   r   r  r   )r/   r   r   r   r   s        r0   _add_created_vertexz GenericGraph._add_created_vertex  s     T]""[f[[[   	V$$$'Vm###0#9DL &3F# .ff%%h///v&'''}V$$r2   c                J     | j         |                     |||||||           S )a  Add a vertex to the graph.

        Parameters
        ----------

        vertex
            A hashable vertex identifier.
        position
            The coordinates where the new vertex should be added. If ``None``, the center
            of the graph is used.
        label
            Controls whether or not the vertex is labeled. If ``False`` (the default),
            the vertex is not labeled; if ``True`` it is labeled using its
            names (as specified in ``vertex``) via :class:`~.MathTex`. Alternatively,
            any :class:`~.Mobject` can be passed to be used as the label.
        label_fill_color
            Sets the fill color of the default labels generated when ``labels``
            is set to ``True``. Has no effect for other values of ``label``.
        vertex_type
            The mobject class used for displaying vertices in the scene.
        vertex_config
            A dictionary containing keyword arguments to be passed to
            the class specified via ``vertex_type``.
        vertex_mobject
            The mobject to be used as the vertex. Overrides all other
            vertex customization options.
        )r   r   r   r   r   r   r   )r  r	  )r/   r   r   r   r   r   r   r   s           r0   _add_vertexzGenericGraph._add_vertex  sD    J (t'  !!1'+- !  

 
	
r2   	positionsr   r   r   r   r   r  1Iterable[tuple[Hashable, Point3D, dict, Mobject]]c                   i i                                   }t                              |          }	|	                               |	t	          t
                    rt                                        nIt	          t                    sJ t                              d          }
|
                               |
t           j                  t	          t                    sJ t           j                                      fd                                D                        fdD              fdD             S )NFc                $    i | ]\  }}|v	||S r.   r.   )rP   r|   valr   s      r0   rR   z1GenericGraph._create_vertices.<locals>.<dictcomp>=  s)    SSS(#ss(?R?RS#?R?R?Rr2   c                H    i | ]}||v r|         nt                    S r.   r	   )rP   rG   r  r   s     r0   rR   z1GenericGraph._create_vertices.<locals>.<dictcomp>?  sH     
 
 
 A$6$6a  DAS<T<T
 
 
r2   c                    g | ]C}                     ||         |         |                             |                     DS ))r   r   r   r   r   r   )r	  r   )	rP   rG   r   r   r  r/   r   r   r   s	     r0   ru   z1GenericGraph._create_vertices.<locals>.<listcomp>D  sp     
 
 
  "1Qi!1'+A..22155    
 
 
r2   )	r  r   r   r   r   r   r
   r   rT   )r/   r  r   r   r   r   r   r   graph_centerbase_positionsbase_labelsr  s   ````````   @r0   _create_verticeszGenericGraph._create_vertices  s    I" O((x>>i((("	fd## 	!]]8V44FFfd+++++--%88Kv&&& F  !;<<M-.....!$"<==!!SSSSm&9&9&;&;SSS	
 	
 	

 
 
 
 

 
 


 
 
 
 
 
 
 
 
 
 
 
 
 	
r2   c               @      fd  j         |||||||dD             S )a"  Add a list of vertices to the graph.

        Parameters
        ----------

        vertices
            Hashable vertex identifiers.
        positions
            A dictionary specifying the coordinates where the new vertices should be added.
            If ``None``, all vertices are created at the center of the graph.
        labels
            Controls whether or not the vertex is labeled. If ``False`` (the default),
            the vertex is not labeled; if ``True`` it is labeled using its
            names (as specified in ``vertex``) via :class:`~.MathTex`. Alternatively,
            any :class:`~.Mobject` can be passed to be used as the label.
        label_fill_color
            Sets the fill color of the default labels generated when ``labels``
            is set to ``True``. Has no effect for other values of ``labels``.
        vertex_type
            The mobject class used for displaying vertices in the scene.
        vertex_config
            A dictionary containing keyword arguments to be passed to
            the class specified via ``vertex_type``.
        vertex_mobjects
            A dictionary whose keys are the vertex identifiers, and whose
            values are mobjects that should be used as vertices. Overrides
            all other vertex customization options.
        c                $    g | ]} j         | S r.   )r  rP   rG   r/   s     r0   ru   z-GenericGraph.add_vertices.<locals>.<listcomp>w  s3     
 
 
 %D$a(
 
 
r2   r  )r  )r/   r  r   r   r   r   r   r   s   `       r0   add_verticeszGenericGraph.add_verticesQ  sX    L
 
 
 
*T*#!1'+ /  
 
 
 	
r2   )	anim_argsc                    i                      dt                      j        |i |d fd}t          fdD              |dS )N	animationscener   c                \    D ]'}|                      |d                     j        |  (d S )Nrb   )remover  )r#  rG   r/   r   s     r0   	on_finishz7GenericGraph._add_vertices_animation.<locals>.on_finish  sE    $ - -QrU###((!,,,- -r2   c              3  6   K   | ]} |d          fi V  dS )rb   Nr.   )rP   rG   r   r"  s     r0   rr   z7GenericGraph._add_vertices_animation.<locals>.<genexpr>  s9      EEii"++++EEEEEEr2   )group
_on_finish)r#  r   )r   r   r  r   )r/   r   r)   r*   r&  r"  r   s   ``   @@r0   _add_vertices_animationz$GenericGraph._add_vertices_animation  s    IMM+v66	/$/@@@	- 	- 	- 	- 	- 	- 	-
 EEEEE_EEE 
 
 
 	
r2   c                <     j         vrt          d d           j                                        j                                        j        v r j                                        j                                       fd j        D             }|D ]} j	                            |            fd|D             }|
                     j                                                    j        |                                    | S )a  Remove a vertex (as well as all incident edges) from the graph.

        Parameters
        ----------

        vertex
            The identifier of a vertex to be removed.

        Returns
        -------

        Group
            A mobject containing all removed objects.

        z5The graph does not contain a vertex with identifier ''c                    g | ]}|v |	S r.   r.   )rP   r   r   s     r0   ru   z/GenericGraph._remove_vertex.<locals>.<listcomp>  s    <<<Q!qr2   c                D    g | ]}j                             |          S r.   )r   r   )rP   r   r/   s     r0   ru   z/GenericGraph._remove_vertex.<locals>.<listcomp>  s'    <<<1TZ^^A&&<<<r2   )r   r?   r   remove_noder  r   r   r   r   r   rN   r%  get_group_class)r/   r   edge_tuplesr   	to_removes   ``   r0   _remove_vertexzGenericGraph._remove_vertex  sD     &&QQQQ   	'''   T\!!LV$$$'''<<<<$*<<< 	% 	%A!!!$$$$<<<<<<<	**622333Y%t##%%y11r2   c                    g }|D ]/}|                     |                     |          j                   0 |                                 | S )a  Remove several vertices from the graph.

        Parameters
        ----------

        vertices
            Vertices to be removed from the graph.

        Examples
        --------
        ::

            >>> G = Graph([1, 2, 3], [(1, 2), (2, 3)])
            >>> removed = G.remove_vertices(2, 3); removed
            VGroup(Line, Line, Dot, Dot)
            >>> G
            Undirected graph on 1 vertices and 0 edges

        )extendr3  submobjectsr0  )r/   r   mobjectsrG   s       r0   remove_verticeszGenericGraph.remove_vertices  sY    (  	@ 	@AOOD//22>????%t##%%x00r2   c                   i                      dt                     | j        | }t          fd|D             d| iS )Nr"  c              3  *   K   | ]} |fi V  d S r   r.   rP   mobjr   r"  s     r0   rr   z:GenericGraph._remove_vertices_animation.<locals>.<genexpr>  5      @@tii**	**@@@@@@r2   r(  )r   r   r8  r   )r/   r   r   r7  r"  s    `  @r0   _remove_vertices_animationz'GenericGraph._remove_vertices_animation  se    IMM+x88	'4'2@@@@@x@@@
HL
 
 	
r2   edgetuple[Hashable, Hashable]c                     | j                                         } fd|D             }|\  }} j                            ||            j                                         }|                    |           |}| j        ||f<    |d |                                          |                                         dd|}| j        ||f<                        |           |	                    |             
                                | S )a  Add a new edge to the graph.

        Parameters
        ----------

        edge
            The edge (as a tuple of vertex identifiers) to be added. If a non-existing
            vertex is passed, a new vertex with default settings will be created. Create
            new vertices yourself beforehand to customize them.
        edge_type
            The mobject class used for displaying edges in the scene.
        edge_config
            A dictionary containing keyword arguments to be passed
            to the class specified via ``edge_type``.

        Returns
        -------
        Group
            A group containing all newly added vertices and edges.

        Nc                L    g | ] }|j         v                    |          !S r.   )r   r  r  s     r0   ru   z*GenericGraph._add_edge.<locals>.<listcomp>  s3    VVV!q?U?U$**1--?U?U?Ur2   rb   startendz_indexr.   )r   r
   r   add_edger   r   r  r   r   rN   r0  )	r/   r?  r   r   added_mobjectsri   rG   base_edge_configedge_mobjects	   `        r0   	_add_edgezGenericGraph._add_edge  s7   6 27799KVVVVtVVV1Q"""388::,,,&$/1a&! y 
q'$$&&Q""$$
 
 	
 
 *
Aq6l+++%t##%%~66r2   r   r   c                   i fd                                 D             } j                                                            |           fdD             D ]1}|                                                 |i                      2t          t          j                   } fd|D             }  j        |i |}	t           fdD             |	          }
  
                                |
 S )a  Add new edges to the graph.

        Parameters
        ----------

        edges
            Edges (as tuples of vertex identifiers) to be added. If a non-existing
            vertex is passed, a new vertex with default settings will be created. Create
            new vertices yourself beforehand to customize them.
        edge_type
            The mobject class used for displaying edges in the scene.
        edge_config
            A dictionary either containing keyword arguments to be passed
            to the class specified via ``edge_type``, or a dictionary
            whose keys are the edge tuples, and whose values are dictionaries
            containing keyword arguments to be passed for the construction
            of the corresponding edge.
        kwargs
            Any further keyword arguments are passed to :meth:`.add_vertices`
            which is used to create new vertices in the passed edges.

        Returns
        -------
        Group
            A group containing all newly added vertices and edges.

        Nc                $    i | ]\  }}|v	||S r.   r.   )rP   rQ   rG   r   s      r0   rR   z*GenericGraph.add_edges.<locals>.<dictcomp>8  s%    VVVfq!qPU~~Q~~~r2   c                :    i | ]}|                                 S r.   r	   )rP   r   rI  s     r0   rR   z*GenericGraph.add_edges.<locals>.<dictcomp>;  s(    FFF1A/4466FFFr2   c                &    g | ]}|j         v|S r.   r   r  s     r0   ru   z*GenericGraph.add_edges.<locals>.<listcomp>A  s%    KKKaAT]4J4J4J4J4Jr2   c              3  ^   K   | ]'}                     ||                    j        V  (dS )rL  N)rK  r6  )rP   r?  r   r   r/   s     r0   rr   z)GenericGraph.add_edges.<locals>.<genexpr>E  s_          ' +D 1         r2   )rT   r   r
   r   r   setitchainr  r   r0  )r/   r   r   r   r*   non_edge_settingsr   edge_verticesnew_verticesadded_verticesrH  rI  s   ````       @r0   	add_edgeszGenericGraph.add_edges  sb   D KVVVV0A0A0C0CVVV388:: 1222FFFFFFF 	? 	?AQ&&{q"'='=>>>>&BHe,--KKKK=KKK**LCFCC      "   

 

 &t##%%~66r2   c                   i                      dt                     | j        |i |}t          fd|D             d| iS )Nr"  c              3  *   K   | ]} |fi V  d S r   r.   r;  s     r0   rr   z4GenericGraph._add_edges_animation.<locals>.<genexpr>Y  r=  r2   r(  )r   r   rY  r   )r/   r   r)   r*   r7  r"  s    `   @r0   _add_edges_animationz!GenericGraph._add_edges_animationQ  sl    IMM+v66	!4>42622@@@@@x@@@
HL
 
 	
r2   tuple[Hashable]c                    || j         vrt          d| d          | j                             |          } | j        j        |  | j                            |d           |                     |           |S )a  Remove an edge from the graph.

        Parameters
        ----------

        edge
            The edge (i.e., a tuple of vertex identifiers) to be removed from the graph.

        Returns
        -------

        Mobject
            The removed edge.

        z#The graph does not contain a edge 'r,  N)r   r?   r   r   remove_edger   r%  )r/   r?  rJ  s      r0   _remove_edgezGenericGraph._remove_edge\  s      tz!!J4JJJKKKz~~d++&&dD)))L!!!r2   c                N      fd|D             }                                   | S )zRemove several edges from the graph.

        Parameters
        ----------
        edges
            Edges to be removed from the graph.

        Returns
        -------
        Group
            A group containing all removed edges.

        c                :    g | ]}                     |          S r.   )r`  )rP   r?  r/   s     r0   ru   z-GenericGraph.remove_edges.<locals>.<listcomp>  s'    CCCT**400CCCr2   )r0  )r/   r   edge_mobjectss   `  r0   remove_edgeszGenericGraph.remove_edgesw  s8     DCCCUCCC%t##%%}55r2   c                   i                      dt                     | j        | }t          fd|D              S )Nr"  c              3  *   K   | ]} |fi V  d S r   r.   r;  s     r0   rr   z7GenericGraph._remove_edges_animation.<locals>.<genexpr>  s5      RR		$ < <) < <RRRRRRr2   )r   r   rd  r   )r/   r   r   r7  r"  s    `  @r0   _remove_edges_animationz$GenericGraph._remove_edges_animation  sT    IMM+x88	$4$e,RRRRRRRRSSr2   nxgraphr   c                ^     | t          |j                  t          |j                  fi |S )a  Build a :class:`~.Graph` or :class:`~.DiGraph` from a
        given ``networkx`` graph.

        Parameters
        ----------

        nxgraph
            A ``networkx`` graph or digraph.
        **kwargs
            Keywords to be passed to the constructor of :class:`~.Graph`.

        Examples
        --------

        .. manim:: ImportNetworkxGraph

            import networkx as nx

            nxgraph = nx.erdos_renyi_graph(14, 0.5)

            class ImportNetworkxGraph(Scene):
                def construct(self):
                    G = Graph.from_networkx(nxgraph, layout="spring", layout_scale=3.5)
                    self.play(Create(G))
                    self.play(*[G[v].animate.move_to(5*RIGHT*np.cos(ind/7 * PI) +
                                                     3*UP*np.sin(ind/7 * PI))
                                for ind, v in enumerate(G.vertices)])
                    self.play(Uncreate(G))

        )r   rA   r   )clsrh  r*   s      r0   from_networkxzGenericGraph.from_networkx  s3    D s4&&W](;(;FFvFFFr2   r   list[list[Hashable]] | Nonec                    |i n|}|	d|vr||d<   |	d|vr||d<   t          | j        |||          | _        | j        D ](}| |                             | j        |                    )| S )a  Change the layout of this graph.

        See the documentation of :class:`~.Graph` for details about the
        keyword arguments.

        Examples
        --------

        .. manim:: ChangeGraphLayout

            class ChangeGraphLayout(Scene):
                def construct(self):
                    G = Graph([1, 2, 3, 4, 5], [(1, 2), (2, 3), (3, 4), (4, 5)],
                              layout={1: [-2, 0, 0], 2: [-1, 0, 0], 3: [0, 0, 0],
                                      4: [1, 0, 0], 5: [2, 0, 0]}
                              )
                    self.play(Create(G))
                    self.play(G.animate.change_layout("circular"))
                    self.wait()
        Nr:   rZ   )rC   r   r   )r   r   r  r   r  )r/   rC   r   r   r:   rZ   rG   s          r0   r   zGenericGraph.change_layout  s    8 ,3!l-&G&G*4M,'"}M'I'I+6M-(.K%'	
 
 
  	- 	-AGOODLO,,,,r2   )r   r   r   r   r   r   r   r`   rC   r   r   r(   r   r   r   r   r   r   r   r   r   r   r:   r;   rZ   r[   r   r   r+   r   )r+   r   r   r   r   r   )r/   r   rG   r   r+   r   )r   r   r   r   r   r   r   r`   r   r   r   r   r   r   r+   r   )
r   r   r   r   r   r   r   r   r+   r   )r   r   r   r   r   r   r   r`   r   r   r   r   r   r   r+   r   )r/   r   r   r   r  r   r   r   r   r`   r   r   r   r   r   r   r+   r  )r/   r   r   r   r  r   r   r   r   r`   r   r   r   r   r   r   )r?  r@  r   r   r   r   )r   r@  r   r   r   r   )r?  r]  )r   r]  )rh  r   )r   r%   NNN)rC   r   r   r(   r   r   r:   rl  rZ   r[   r+   r   ) r4   r5   r6   r7   r"   r   r   r   staticmethodr   r   r   r	  r  r  r  r  r   r*  r3  r8  r>  rK  rY  r\  r`  rd  rg  classmethodrk  r   __classcell__)r   s   @r0   r   r     s^       Q Qn $ %LT;<%)%(%)'+#':>'+#'`, `, `, `, `, `, `,D N N N \NN N N N        (, %%(%)&*+D +D +D +D +DZ% % % %: (, %%(%)&*/
 /
 /
 /
 /
h "& %%(%)'+4
 4
 4
 4
 4
 4
r "& %%(%)'+1
 1
 1
 1
 1
 1
f l##7; 
 
 
 
 $#
&"2 "2 "2H1 1 12 o&&>B 	
 	
 	
 	
 '&	
 $(#'	17 17 17 17 17l $(#'	;7 ;7 ;7 ;7 ;7 ;7z i  48 
 
 
 
 ! 
   66 6 6 6" l##8< T T T T $#T !G !G !G [!GJ MU;</326'++ + + + + + + + +r2   r   )	metaclassc                  @    e Zd ZdZedd            Zdd	Zd
 ZddZdS )r   a$.  An undirected graph (vertices connected with edges).

    The graph comes with an updater which makes the edges stick to
    the vertices when moved around. See :class:`.DiGraph` for
    a version with directed edges.

    See also
    --------

    :class:`.GenericGraph`

    Parameters
    ----------

    vertices
        A list of vertices. Must be hashable elements.
    edges
        A list of edges, specified as tuples ``(u, v)`` where both ``u``
        and ``v`` are vertices. The vertex order is irrelevant.
    labels
        Controls whether or not vertices are labeled. If ``False`` (the default),
        the vertices are not labeled; if ``True`` they are labeled using their
        names (as specified in ``vertices``) via :class:`~.MathTex`. Alternatively,
        custom labels can be specified by passing a dictionary whose keys are
        the vertices, and whose values are the corresponding vertex labels
        (rendered via, e.g., :class:`~.Text` or :class:`~.Tex`).
    label_fill_color
        Sets the fill color of the default labels generated when ``labels``
        is set to ``True``. Has no effect for other values of ``labels``.
    layout
        Either one of ``"spring"`` (the default), ``"circular"``, ``"kamada_kawai"``,
        ``"planar"``, ``"random"``, ``"shell"``, ``"spectral"``, ``"spiral"``, ``"tree"``, and ``"partite"``
        for automatic vertex positioning using ``networkx``
        (see `their documentation <https://networkx.org/documentation/stable/reference/drawing.html#module-networkx.drawing.layout>`_
        for more details), or a dictionary specifying a coordinate (value)
        for each vertex (key) for manual positioning.
    layout_config
        Only for automatically generated layouts. A dictionary whose entries
        are passed as keyword arguments to the automatic layout algorithm
        specified via ``layout`` of ``networkx``.
        The ``tree`` layout also accepts a special parameter ``vertex_spacing``
        passed as a keyword argument inside the ``layout_config`` dictionary.
        Passing a tuple ``(space_x, space_y)`` as this argument overrides
        the value of ``layout_scale`` and ensures that vertices are arranged
        in a way such that the centers of siblings in the same layer are
        at least ``space_x`` units apart horizontally, and neighboring layers
        are spaced ``space_y`` units vertically.
    layout_scale
        The scale of automatically generated layouts: the vertices will
        be arranged such that the coordinates are located within the
        interval ``[-scale, scale]``. Some layouts accept a tuple ``(scale_x, scale_y)``
        causing the first coordinate to be in the interval ``[-scale_x, scale_x]``,
        and the second in ``[-scale_y, scale_y]``. Default: 2.
    vertex_type
        The mobject class used for displaying vertices in the scene.
    vertex_config
        Either a dictionary containing keyword arguments to be passed to
        the class specified via ``vertex_type``, or a dictionary whose keys
        are the vertices, and whose values are dictionaries containing keyword
        arguments for the mobject related to the corresponding vertex.
    vertex_mobjects
        A dictionary whose keys are the vertices, and whose values are
        mobjects to be used as vertices. Passing vertices here overrides
        all other configuration options for a vertex.
    edge_type
        The mobject class used for displaying edges in the scene.
    edge_config
        Either a dictionary containing keyword arguments to be passed
        to the class specified via ``edge_type``, or a dictionary whose
        keys are the edges, and whose values are dictionaries containing
        keyword arguments for the mobject related to the corresponding edge.


    Examples
    --------

    First, we create a small graph and demonstrate that the edges move
    together with the vertices.

    .. manim:: MovingVertices

        class MovingVertices(Scene):
            def construct(self):
                vertices = [1, 2, 3, 4]
                edges = [(1, 2), (2, 3), (3, 4), (1, 3), (1, 4)]
                g = Graph(vertices, edges)
                self.play(Create(g))
                self.wait()
                self.play(g[1].animate.move_to([1, 1, 0]),
                          g[2].animate.move_to([-1, 1, 0]),
                          g[3].animate.move_to([1, -1, 0]),
                          g[4].animate.move_to([-1, -1, 0]))
                self.wait()

    There are several automatic positioning algorithms to choose from:

    .. manim:: GraphAutoPosition
        :save_last_frame:

        class GraphAutoPosition(Scene):
            def construct(self):
                vertices = [1, 2, 3, 4, 5, 6, 7, 8]
                edges = [(1, 7), (1, 8), (2, 3), (2, 4), (2, 5),
                         (2, 8), (3, 4), (6, 1), (6, 2),
                         (6, 3), (7, 2), (7, 4)]
                autolayouts = ["spring", "circular", "kamada_kawai",
                               "planar", "random", "shell",
                               "spectral", "spiral"]
                graphs = [Graph(vertices, edges, layout=lt).scale(0.5)
                          for lt in autolayouts]
                r1 = VGroup(*graphs[:3]).arrange()
                r2 = VGroup(*graphs[3:6]).arrange()
                r3 = VGroup(*graphs[6:]).arrange()
                self.add(VGroup(r1, r2, r3).arrange(direction=DOWN))

    Vertices can also be positioned manually:

    .. manim:: GraphManualPosition
        :save_last_frame:

        class GraphManualPosition(Scene):
            def construct(self):
                vertices = [1, 2, 3, 4]
                edges = [(1, 2), (2, 3), (3, 4), (4, 1)]
                lt = {1: [0, 0, 0], 2: [1, 1, 0], 3: [1, -1, 0], 4: [-1, 0, 0]}
                G = Graph(vertices, edges, layout=lt)
                self.add(G)

    The vertices in graphs can be labeled, and configurations for vertices
    and edges can be modified both by default and for specific vertices and
    edges.

    .. note::

        In ``edge_config``, edges can be passed in both directions: if
        ``(u, v)`` is an edge in the graph, both ``(u, v)`` as well
        as ``(v, u)`` can be used as keys in the dictionary.

    .. manim:: LabeledModifiedGraph
        :save_last_frame:

        class LabeledModifiedGraph(Scene):
            def construct(self):
                vertices = [1, 2, 3, 4, 5, 6, 7, 8]
                edges = [(1, 7), (1, 8), (2, 3), (2, 4), (2, 5),
                         (2, 8), (3, 4), (6, 1), (6, 2),
                         (6, 3), (7, 2), (7, 4)]
                g = Graph(vertices, edges, layout="circular", layout_scale=3,
                          labels=True, vertex_config={7: {"fill_color": RED}},
                          edge_config={(1, 7): {"stroke_color": RED},
                                       (2, 7): {"stroke_color": RED},
                                       (4, 7): {"stroke_color": RED}})
                self.add(g)

    You can also lay out a partite graph on columns by specifying
    a list of the vertices on each side and choosing the partite layout.

    .. note::

        All vertices in your graph which are not listed in any of the partitions
        are collected in their own partition and rendered in the rightmost column.

    .. manim:: PartiteGraph
        :save_last_frame:

        import networkx as nx

        class PartiteGraph(Scene):
            def construct(self):
                G = nx.Graph()
                G.add_nodes_from([0, 1, 2, 3])
                G.add_edges_from([(0, 2), (0,3), (1, 2)])
                graph = Graph(list(G.nodes), list(G.edges), layout="partite", partitions=[[0, 1]])
                self.play(Create(graph))

    The representation of a linear artificial neural network is facilitated
    by the use of the partite layout and defining partitions for each layer.

    .. manim:: LinearNN
        :save_last_frame:

        class LinearNN(Scene):
            def construct(self):
                edges = []
                partitions = []
                c = 0
                layers = [2, 3, 3, 2]  # the number of neurons in each layer

                for i in layers:
                    partitions.append(list(range(c + 1, c + i + 1)))
                    c += i
                for i, v in enumerate(layers[1:]):
                        last = sum(layers[:i+1])
                        for j in range(v):
                            for k in range(last - layers[i], last):
                                edges.append((k + 1, j + last + 1))

                vertices = np.arange(1, sum(layers) + 1)

                graph = Graph(
                    vertices,
                    edges,
                    layout='partite',
                    partitions=partitions,
                    layout_scale=3,
                    vertex_config={'radius': 0.20},
                )
                self.add(graph)

    The custom tree layout can be used to show the graph
    by distance from the root vertex. You must pass the root vertex
    of the tree.

    .. manim:: Tree

        import networkx as nx

        class Tree(Scene):
            def construct(self):
                G = nx.Graph()

                G.add_node("ROOT")

                for i in range(5):
                    G.add_node("Child_%i" % i)
                    G.add_node("Grandchild_%i" % i)
                    G.add_node("Greatgrandchild_%i" % i)

                    G.add_edge("ROOT", "Child_%i" % i)
                    G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
                    G.add_edge("Grandchild_%i" % i, "Greatgrandchild_%i" % i)

                self.play(Create(
                    Graph(list(G.nodes), list(G.edges), layout="tree", root_vertex="ROOT")))

    The following code sample illustrates the use of the ``vertex_spacing``
    layout parameter specific to the ``"tree"`` layout. As mentioned
    above, setting ``vertex_spacing`` overrides the specified value
    for ``layout_scale``, and as such it is harder to control the size
    of the mobject. However, we can adjust the captured frame and
    zoom out by using a :class:`.MovingCameraScene`::

        class LargeTreeGeneration(MovingCameraScene):
            DEPTH = 4
            CHILDREN_PER_VERTEX = 3
            LAYOUT_CONFIG = {"vertex_spacing": (0.5, 1)}
            VERTEX_CONF = {"radius": 0.25, "color": BLUE_B, "fill_opacity": 1}

            def expand_vertex(self, g, vertex_id: str, depth: int):
                new_vertices = [
                    f"{vertex_id}/{i}" for i in range(self.CHILDREN_PER_VERTEX)
                ]
                new_edges = [(vertex_id, child_id) for child_id in new_vertices]
                g.add_edges(
                    *new_edges,
                    vertex_config=self.VERTEX_CONF,
                    positions={
                        k: g.vertices[vertex_id].get_center() + 0.1 * DOWN
                        for k in new_vertices
                    },
                )
                if depth < self.DEPTH:
                    for child_id in new_vertices:
                        self.expand_vertex(g, child_id, depth + 1)

                return g

            def construct(self):
                g = Graph(["ROOT"], [], vertex_config=self.VERTEX_CONF)
                g = self.expand_vertex(g, "ROOT", 1)
                self.add(g)

                self.play(
                    g.animate.change_layout(
                        "tree",
                        root_vertex="ROOT",
                        layout_config=self.LAYOUT_CONFIG,
                    )
                )
                self.play(self.camera.auto_zoom(g, margin=1), run_time=0.5)
    r+   nx.Graphc                 (    t          j                    S r   )rB   r   r.   r2   r0   r   zGraph._empty_networkx_graph  s    xzzr2   r   r   r   r   c                2      fd|D              _         d S )Nc           
         i | ]Q\  }}||f d|                                          |                                          d dj        ||f         RS rb   rC  r.   )r  r   rP   ri   rG   r   r/   s      r0   rR   z-Graph._populate_edge_dict.<locals>.<dictcomp>  s     
 
 
 A FII 1g((**G&&((  #QF+	 
 
 
r2   )r   r   s   ` `r0   r   zGraph._populate_edge_dict  s9    
 
 
 
 
  
 
 



r2   c           
     @   |j                                         D ]\  \  }}}|                    ||                                         ||                                         | j                            dd          | j                            dd                     d S )Nbuffr   path_arcr{  r|  )r   rT   set_points_by_endsr  r   r   )r/   r&   ri   rG   r?  s        r0   r   zGraph.update_edges  s    !K--// 	 	LFQD##a##%%a##%%&**6155*..z1==	 $    	 	r2   r/   r`   c                \    dt          | j                   dt          | j                   dS )NzUndirected graph on  vertices and  edgesr>   r   r   r/   s    r0   __repr__zGraph.__repr__  s-    _c$-&8&8__DJ____r2   N)r+   rt  rn  )r/   r   r+   r`   	r4   r5   r6   r7   ro  r   r   r   r  r.   r2   r0   r   r     s~        X Xt    \
 
 
 
  ` ` ` ` ` `r2   c                  @    e Zd ZdZedd            Zdd	Zd
 ZddZdS )r   a  A directed graph.

    .. note::

        In contrast to undirected graphs, the order in which vertices in a given
        edge are specified is relevant here.

    See also
    --------

    :class:`.GenericGraph`

    Parameters
    ----------

    vertices
        A list of vertices. Must be hashable elements.
    edges
        A list of edges, specified as tuples ``(u, v)`` where both ``u``
        and ``v`` are vertices. The edge is directed from ``u`` to ``v``.
    labels
        Controls whether or not vertices are labeled. If ``False`` (the default),
        the vertices are not labeled; if ``True`` they are labeled using their
        names (as specified in ``vertices``) via :class:`~.MathTex`. Alternatively,
        custom labels can be specified by passing a dictionary whose keys are
        the vertices, and whose values are the corresponding vertex labels
        (rendered via, e.g., :class:`~.Text` or :class:`~.Tex`).
    label_fill_color
        Sets the fill color of the default labels generated when ``labels``
        is set to ``True``. Has no effect for other values of ``labels``.
    layout
        Either one of ``"spring"`` (the default), ``"circular"``, ``"kamada_kawai"``,
        ``"planar"``, ``"random"``, ``"shell"``, ``"spectral"``, ``"spiral"``, ``"tree"``, and ``"partite"``
        for automatic vertex positioning using ``networkx``
        (see `their documentation <https://networkx.org/documentation/stable/reference/drawing.html#module-networkx.drawing.layout>`_
        for more details), or a dictionary specifying a coordinate (value)
        for each vertex (key) for manual positioning.
    layout_config
        Only for automatically generated layouts. A dictionary whose entries
        are passed as keyword arguments to the automatic layout algorithm
        specified via ``layout`` of ``networkx``.
        The ``tree`` layout also accepts a special parameter ``vertex_spacing``
        passed as a keyword argument inside the ``layout_config`` dictionary.
        Passing a tuple ``(space_x, space_y)`` as this argument overrides
        the value of ``layout_scale`` and ensures that vertices are arranged
        in a way such that the centers of siblings in the same layer are
        at least ``space_x`` units apart horizontally, and neighboring layers
        are spaced ``space_y`` units vertically.
    layout_scale
        The scale of automatically generated layouts: the vertices will
        be arranged such that the coordinates are located within the
        interval ``[-scale, scale]``. Some layouts accept a tuple ``(scale_x, scale_y)``
        causing the first coordinate to be in the interval ``[-scale_x, scale_x]``,
        and the second in ``[-scale_y, scale_y]``. Default: 2.
    vertex_type
        The mobject class used for displaying vertices in the scene.
    vertex_config
        Either a dictionary containing keyword arguments to be passed to
        the class specified via ``vertex_type``, or a dictionary whose keys
        are the vertices, and whose values are dictionaries containing keyword
        arguments for the mobject related to the corresponding vertex.
    vertex_mobjects
        A dictionary whose keys are the vertices, and whose values are
        mobjects to be used as vertices. Passing vertices here overrides
        all other configuration options for a vertex.
    edge_type
        The mobject class used for displaying edges in the scene.
    edge_config
        Either a dictionary containing keyword arguments to be passed
        to the class specified via ``edge_type``, or a dictionary whose
        keys are the edges, and whose values are dictionaries containing
        keyword arguments for the mobject related to the corresponding edge.
        You can further customize the tip by adding a ``tip_config`` dictionary
        for global styling, or by adding the dict to a specific ``edge_config``.

    Examples
    --------

    .. manim:: MovingDiGraph

        class MovingDiGraph(Scene):
            def construct(self):
                vertices = [1, 2, 3, 4]
                edges = [(1, 2), (2, 3), (3, 4), (1, 3), (1, 4)]

                g = DiGraph(vertices, edges)

                self.add(g)
                self.play(
                    g[1].animate.move_to([1, 1, 1]),
                    g[2].animate.move_to([-1, 1, 2]),
                    g[3].animate.move_to([1, -1, -1]),
                    g[4].animate.move_to([-1, -1, 0]),
                )
                self.wait()

    You can customize the edges and arrow tips globally or locally.

    .. manim:: CustomDiGraph

        class CustomDiGraph(Scene):
            def construct(self):
                vertices = [i for i in range(5)]
                edges = [
                    (0, 1),
                    (1, 2),
                    (3, 2),
                    (3, 4),
                ]

                edge_config = {
                    "stroke_width": 2,
                    "tip_config": {
                        "tip_shape": ArrowSquareTip,
                        "tip_length": 0.15,
                    },
                    (3, 4): {
                        "color": RED,
                        "tip_config": {"tip_length": 0.25, "tip_width": 0.25}
                    },
                }

                g = DiGraph(
                    vertices,
                    edges,
                    labels=True,
                    layout="circular",
                    edge_config=edge_config,
                ).scale(1.4)

                self.play(Create(g))
                self.wait()

    Since this implementation respects the labels boundary you can also use
    it for an undirected moving graph with labels.

    .. manim:: UndirectedMovingDiGraph

        class UndirectedMovingDiGraph(Scene):
            def construct(self):
                vertices = [i for i in range(5)]
                edges = [
                    (0, 1),
                    (1, 2),
                    (3, 2),
                    (3, 4),
                ]

                edge_config = {
                    "stroke_width": 2,
                    "tip_config": {"tip_length": 0, "tip_width": 0},
                    (3, 4): {"color": RED},
                }

                g = DiGraph(
                    vertices,
                    edges,
                    labels=True,
                    layout="circular",
                    edge_config=edge_config,
                ).scale(1.4)

                self.play(Create(g))
                self.wait()

                self.play(
                    g[1].animate.move_to([1, 1, 1]),
                    g[2].animate.move_to([-1, 1, 2]),
                    g[3].animate.move_to([-1.5, -1.5, -1]),
                    g[4].animate.move_to([1, -2, -1]),
                )
                self.wait()

    r+   
nx.DiGraphc                 (    t          j                    S r   )rB   r   r.   r2   r0   r   zDiGraph._empty_networkx_graph  s    z||r2   r   r   r   r   c                      fd|D              _          j                                         D ]"\  \  }}} |j        di  j        ||f          #d S )Nc           
     f    i | ]-\  }}||f d|         |         d dj         ||f         .S rx  )r   ry  s      r0   rR   z/DiGraph._populate_edge_dict.<locals>.<dictcomp>  sr     
 
 
 A FII 1gG  #QF+	 
 
 
r2   r.   )r   rT   add_tipr   )r/   r   r   ri   rG   r?  s   ` `   r0   r   zDiGraph._populate_edge_dict  s    
 
 
 
 
  
 
 

 !J,,.. 	5 	5LFQDDL444+QF34444	5 	5r2   c           
     V   |j                                         D ]\  \  }}}|                                d         }|                    ||         ||         | j                            dd          | j                            dd                     |                    |           dS )zUpdates the edges to stick at their corresponding vertices.

        Arrow tips need to be repositioned since otherwise they can be
        deformed.
        r   r{  r|  r}  N)r   rT   pop_tipsr~  r   r   r  )r/   r&   ri   rG   r?  tips         r0   r   zDiGraph.update_edges  s     "K--// 
	 
	LFQD--//!$C ##aa&**6155*..z1==	 $    LL
	 
	r2   r/   r`   c                \    dt          | j                   dt          | j                   dS )NzDirected graph on r  r  r  r  s    r0   r  zDiGraph.__repr__  s-    ]C$6$6]]c$*oo]]]]r2   N)r+   r  rn  )r/   r   r+   r`   r  r.   r2   r0   r   r     s~        m m^    \5 5 5 5   $^ ^ ^ ^ ^ ^r2   )r%   N)
r8   r   r'   r9   r:   r;   r*   r   r+   r,   r3   )r8   r   r'   r9   r*   r   )Nr%   NrX   )
rY   r   rZ   r[   r'   r\   r]   r^   r_   r`   )r   r%   N)
r8   r   rC   r   r   r(   r   r   r+   r   )Ir7   
__future__r   __all__	itertoolsrS  collections.abcr   r   r   r
   typingr   r   r   r   r   networkxrB   numpyrM   r   manim.scene.scener   manim.typingr   r   classesr&   r   digraphr   r   __annotations__manim.animation.compositionr   manim.animation.creationr   r   manim.mobject.geometry.arcr   r   manim.mobject.geometry.liner   manim.mobject.mobjectr   r   )manim.mobject.opengl.opengl_compatibilityr   #manim.mobject.opengl.opengl_mobjectr   manim.mobject.text.tex_mobjectr    &manim.mobject.types.vectorized_mobjectr!   manim.utils.colorr"   r$   rH   rW   r   
LayoutNamerC   circular_layoutkamada_kawai_layoutplanar_layoutshell_layoutspectral_layoutspiral_layoutspring_layoutr   r   r   r.   r2   r0   <module>r     sZ   X X X " " " " " " 
     8 8 8 8 8 8 8 8 8 8       > > > > > > > > > > > > > >         M      ''''''11111111)/"*2D2LLGLLLL 6 6 6 6 6 6 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 , , , , , , ; ; ; ; ; ; ; ; E E E E E E = = = = = = 2 2 2 2 2 2 ; ; ; ; ; ; # # # # # #s s s s sX s s sp 6:J J J J J4B B B B B $("##'_Q _Q _Q _Q _QD 	
 ^RY%>??D)FGGtNO44d>29#:;;d>>22T.")"899^RY%>??d>29#:;;d>29#:;;D... .      IQ78+/	         FB B B B B8 B B B BJw` w` w` w` w`L w` w` w`t	W^ W^ W^ W^ W^l W^ W^ W^ W^ W^r2   