
    b-0                         d dl Z d dlZd dlmZ 	 	 ddZ G d de          Zd Zd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd ZddZ	 	 	 	 	 	 ddZd ZdS )    N)	dot_graphc                 :   t          ||fd|i|}|r| d|                    dd          z   z  } t          j                            |d| z            }| |d|z             t          |d          }	|	                    |           |	                                 d S )Ntitle_,  z%s.dotzwriting graph to %sw)r   replaceospathjoinopenwriteclose)
basename	edge_listverticeslabeldot_file_dirdebugkwargssfilenamefs
             7/usr/lib/python3/dist-packages/samba/kcc/graph_utils.pywrite_dot_filer      s    (I==U=f==A 2C%--b1111w||L(X*=>>H#h.///XsAGGAJJJGGIIIII    c                       e Zd ZdS )
GraphErrorN)__name__
__module____qualname__ r   r   r   r   *   s        Dr   r   c                    |D ]}t                      }| D ]<\  }}||k    r|                    |           !||k    r|                    |           =t          |          dz   t          |          k    rt          d          dS )zXThe graph is complete, which is to say there is an edge between
    every pair of nodes.   zgraph is not fully connectedN)setaddlenr   )edgesr   edge_verticesvremotesabs          r   verify_graph_completer/   .   s      = =%% 	 	DAqAvvAaAw<<!s8}},,;<<< -= =r   c                   
 | s$t          |          dk    rdS t          d          t          |           }t          |                                          
	 g }t          |          D ]g\  }}|\  }}|
v r+
                    |           |                    |           9|
v r*
                    |           |                    |           h|snt          |          D ]}||= |s
t          |          k    rBd}	|	d	                    
fdt          |          D                       z  }	t          |	          dS )z&There is a path between any two nodes.r%   Nz9all vertices are disconnected because there are no edges:TzHthe graph is not connected, as the following vertices are unreachable:
 z
 c              3   $   K   | ]
}|v|V  d S Nr#   ).0r+   reacheds     r   	<genexpr>z)verify_graph_connected.<locals>.<genexpr>X   s9       - -aG++ ++++- -r   )r(   r   listr&   pop	enumerater'   appendreversedr   sorted)r)   r   r*   remaining_edgesdoomedier-   r.   r   r4   s             @r   verify_graph_connectedr@   <   s    0x==AF / 0 0 	0 5kkO/%%''((G#o.. 	! 	!DAqDAqG||Aa    gAa    	&!! 	# 	#A""#  'S]]22=	UZZ - - - -6(#3#3 - - - - - 	-mm 32r   c                 &   t          |           dk    rt          | ||          S t          j        | t          |           dz
            D ]F}	 t          |||           # t          $ r%}| D ]}||vrt	          d|z            Y d}~?d}~ww xY wdS )z:The graph stays connected when any single edge is removed.r   r%   zFThe graph will be disconnected when the connection from %s to %s failsN)r(   r@   	itertoolscombinationsr   )r)   r   r*   subsetr?   edges         r   *verify_graph_connected_under_edge_failuresrF   ]   s    
5zzQ%eX}EEE(E

Q?? N N	N"68]CCCC 	N 	N 	N N Nv%%$ &FHL&M N N N &N N N N N	NN Ns   A
B)B		Bc                 l    |D ]/fd|D             }fd| D             }t          |||           0dS )z<The graph stays connected when any single vertex is removed.c                     g | ]}|u|	S r#   r#   r3   xr+   s     r   
<listcomp>z@verify_graph_connected_under_vertex_failures.<locals>.<listcomp>p   s    :::aqzzzzzr   c                     g | ]}|v|	S r#   r#   rI   s     r   rK   z@verify_graph_connected_under_vertex_failures.<locals>.<listcomp>q   s    4441!Qr   N)r@   )r)   r   r*   sub_vertices	sub_edgesr+   s        @r   ,verify_graph_connected_under_vertex_failuresrO   l   si      F F::::8:::4444444	y,EEEEF Fr   c           	          d | D             }	 t          j        |d          D ]S\  }}||z  }|rGt          |          dk    r||z  }|                    |            nt	          d|d| d|          TdS l)	zThe graph contains no loops.c                 ,    g | ]}t          |          S r#   r&   r3   r?   s     r   rK   z'verify_graph_forest.<locals>.<listcomp>w   s    ###SVV###r   T   r%   z'there is a loop in the graph
 vertices z
 edges z
 intersection N)rB   rC   r(   remover   )r)   r   r*   treesr-   r.   intersections          r   verify_graph_forestrX   u   s    ##U###E*5!44 	 	DAqq5L 	F|$$))FALLOOOE$* '/hh||&E F F F	F" F)r   c                     t          |           }d |D             }	 t          j        |d          D ]J\  }}||z  }|r>t          |          dk    r||z  }|                    |            nt          d          KdS c)a,  This allows a forest with duplicate edges. That is if multiple
    edges go between the same two vertices, they are treated as a
    single edge by this test.

    e.g.:
                        o
    pass: o-o=o  o=o   (|)             fail:  o-o
            `o          o                     `o'
    c                 ,    g | ]}t          |          S r#   rR   rS   s     r   rK   z2verify_graph_multi_edge_forest.<locals>.<listcomp>   s    ***SVV***r   TrT   r%   zthere is a loop in the graphN)r&   rB   rC   r(   rU   r   )r)   r   r*   unique_edgesrV   r-   r.   rW   s           r   verify_graph_multi_edge_forestr\      s     u::L**\***E*5!44 
	 
	DAqq5L E|$$))FALLOOOE$%CDDDE Fr   c                     t          |          t          |          z
  }|r2t          dd                    t          |                    z            dS )z$There are no vertices without edges.z#some vertices are not connected:
%s
Nr&   r   r   r;   )r)   r   r*   lonelys       r   verify_graph_no_lonely_verticesra      s[    ]]S///F 4?6&>>223 4 4 	44 4r   c                     t          |          t          |          z
  }|r2t          dd                    t          |                    z            dS )zBThe edge endpoints contain no vertices that are otherwise unknown.z,some edge vertices are seemingly unknown:
%sr^   Nr_   )r)   r   r*   unknowns       r    verify_graph_no_unknown_verticesrd      s[    -  3x==0G 5H6'??334 5 5 	55 5r   c                    | st          |          dk    rdS t          |           dt          |          z  k     rt          d          t          |           }t                      }| D ]Y}|d         |d         f}||v rC||v r?|                    |           |                    |           |                    |           Zi }|D ]o\  }}	|                    |t                                                    |	           |                    |	t                                                    |           p|                                D ]*\  }
}t          |          dk    rt          d|
z            +t          |                                          D ]S}
||
         }|s|D ]@|         }|                    |
           |	                    fd|D                        A||
= Tt          |          dk    r7t          dd	
                    |                                          z            t          |||           t          |||           dS )
a7  Each node has at least two directed edges leaving it, and two
    arriving. The edges work in pairs that have the same end points
    but point in opposite directions. The pairs form a path that
    touches every vertex and form a loop.

    There might be other connections that *aren't* part of the ring.

    Deciding this for sure is NP-complete (the Hamiltonian path
    problem), but there are some easy failures that can be detected.
    So far we check for:
      - leaf nodes
      - disjoint subgraphs
      - robustness against edge and vertex failure
    r%   NrT   zFdirected double ring requires at least twice as many edges as verticesr   z2wanted double directed ring, found a leaf node(%s)c              3   (   K   | ]}|k    |V  d S r2   r#   )r3   rJ   ns     r   r5   z4verify_graph_directed_double_ring.<locals>.<genexpr>   s'      ::a1666666::r   zZwanted double directed ring, but this looks like a split graph
(%s can't reach each other)r   )r(   r   r&   r'   rU   
setdefaultitemsr6   keysupdater   rF   rO   )r)   r   r*   half_duplexduplex_linksrE   rev_edgeedge_mapr-   r.   vertex
neighboursnsetn_neighboursrg   s                 @r   !verify_graph_directed_double_ringrt      s   $  S]]a''
5zzAH%%% 5 6 6 	6 e**K55L ) )GT!W%;8{#:#:T"""t$$$x((( H - -1Asuu%%))!,,,Asuu%%))!,,,, 'nn.. . .
z??a $&,- . . .   x}}''   	 	; 	;A#A;L'''::::4:::::::V
8}}q 7 8==??334 5 5 	5
 /|X/<> > >0x1>@ @ @ @ @r   c                 6   t          |          dk     rdS t          |          dk    ra	 t          |           dk    r>| d         d         | d         d         k    r | d         d         | d         d         k    rdS t          d          t          | ||          S )zThis performs the directed_double_ring test but makes special
    concessions for small rings where the strict rules don't really
    apply.rT   Nr   r%   z0A two vertex graph should have an edge each way.)r(   r   rt   )r)   r   r*   s      r   *verify_graph_directed_double_ring_or_smallrv   	  s     8}}q
8}}LJJ!OO!HQK58A;&&!HQK58A;&&FKLLL,UHmLLLr   Fr#   c                    g }d |D             }t                      }| D ]/\  }}|                    |           |                    |           0||}nt          |          }|D ]]}d|z  }	t                      |	         }
	  |
| ||           *# t          $ r'}|                    |||
j        f           Y d }~Vd }~ww xY w|S )Nc                 :    g | ]}|                     d d          S ) r   )r
   )r3   rJ   s     r   rK   z verify_graph.<locals>.<listcomp>  s&    :::!!))C%%:::r   zverify_graph_%s)r&   r'   globalsr   r9   __doc__)r)   r   directed
propertieserrorsr*   r-   r.   pfnr   r?   s               r   verify_graphr     s   F::z:::JEEM  1!! x== - -"IIbM	-AeX}---- 	- 	- 	-MM1a+,,,,,,,,	- Ms   B
C B;;C Tc                 >   |
t          | ||||
||||||           |	rzt          |||          }|rh| d|pd} |d|z             |D ]\  }}} |d|dd|           |r6t          d|d	d
                    d |D                                 d S d S d S )N)	r   r   r   reformat_labelsr|   r   edge_colorsedge_labelsvertex_colors)r}   ry   r   z
%s FAILED:z>18: zThe 'z(' graph lacks the following properties:
r^   c              3   ,   K   | ]\  }}}|d |V  dS )r   Nr#   )r3   r   r?   docs       r   r5   z!verify_and_dot.<locals>.<genexpr>L  sQ       3L 3L7@q!S @Aqq!!3D 3L 3L 3L 3L 3L 3Lr   )r   r   r   r   )r   r)   r   r   r   r|   r}   fatalr   verifyr   r   r   r   r~   r   r   r?   r   s                      r   verify_and_dotr   3  sX    x$0'6"#.m		M 	M 	M 	M  NeX)35 5 5 		N'xx"5EE,&'''# , ,	1cQQQQ*++++ N j"'%% 3L 3LDJ3L 3L 3L *L *L *L"M N N NN N		N 		N
N Nr   c                  Z   t          t                                                                D ]|\  } }|                     d          rbt	          |                     dd                     |j        r*t	          d|j                                        z             nt	                       }d S )Nverify_graph_r   z    %s)r;   rz   ri   
startswithprintr
   r{   rstrip)kr+   s     r   list_verify_testsr   P  s    wyy(())  1<<(( 	!))OR00111y h!)"2"2"4"456666 r   )NNNN)NFr#   )NNTFr#   TNTNNNN)r   rB   samba.graphr   r   	Exceptionr   r/   r@   rF   rO   rX   r\   ra   rd   rt   rv   r   r   r   r#   r   r   <module>r      su  * 
			     ! ! ! ! ! ! >B,0   	 	 	 	 	 	 	 	= = =  BN N NF F F  4  44 4 45 5 5M@ M@ M@`M M M"   2 :>2748-115!%N N N N:    r   