ó žÃÒYc@sÁdZdZdgZddlmZddlmZddlZddl m Z dd l m Z dd l m Z dd l m Z d „Ze d ƒd„ƒZd„Zddde d„ZdS(s/ Capacity scaling minimum cost flow algorithm. s&ysitu tcapacity_scalingiÿÿÿÿ(tchain(tlogNi(t BinaryHeap(tgenerate_unique_node(tnot_implemented_for(tarbitrary_elementc Cstƒ}tjƒ}|j|ƒ|jd}tdƒ}x|D]•}xŒ||jƒD]z\}}|}x@|jƒD]2\} }|d|krxt||dƒ}qxqxW||krY|j||d|ƒqYqYWqBWtj |ƒrütj dƒ‚ndS(s.Detect infinite-capacity negative cycles. tinftcapacitytweightsUNegative cost cycle of infinite capacity found. Min cost flow may be unbounded below.N( RtnxtDiGraphtadd_nodes_fromtgraphtfloattitemstmintadd_edgetnegative_edge_cycletNetworkXUnbounded( tRtstGRtf_inftutvtetwtk((s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pyt_detect_unboundednesss        !t undirectedc s¸t‡‡fd†ˆDƒƒdkr7tjdƒ‚ntjƒ‰ˆj‡‡fd†ˆDƒƒtdƒ‰xhtjˆdtƒD]Q\}}}|j|dƒdkr…|jˆˆƒˆkr…tj dƒ‚q…q…Wˆj ƒrPgˆj dtdtƒD]H\}}}}||krÿ|jˆˆƒdkrÿ||||f^qÿ}n^gˆj dtƒD]E\}}}||krc|jˆˆƒdkrc||d|f^qc}t t‡fd †ˆDƒƒd t‡‡fd †|Dƒƒƒpód ‰x¤|D]œ\}}}}t |jˆˆƒˆƒ} |j|dƒ} ˆj||d |tfd| d| ddƒˆj||d |tfddd| ddƒqýWˆˆjd4sisSum of the demands should be 0.c3s=|]3}|iˆj|jˆdƒ d6dd6fVqdS(itexcesst potentialN(RR (R!R(RR"(s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pys 8sRtdatasUNegative cost cycle of infinite capacity found. Min cost flow may be unbounded below.tkeysc3s&|]}tˆj|dƒVqdS(R#N(tabsR(R!R(R(s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pys Psic3sA|]7\}}}}ˆ|kr|ˆˆkr|ˆVqdS(N((R!RRRR(RR(s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pys QsitkeyRR tflow(tsumR tNetworkXUnfeasiblet MultiDiGraphR Rtselfloop_edgestTrueR Rt is_multigraphtedgestmaxRRtFalseR R( RR"RR RRRRt edge_listtrR((RRRR"Rs~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pyt_build_residual_network0s6%   %0 (?"<&.3  csYtdƒ‰i}|jƒrìx4|D]À‰i|ˆoscss9|]/\}}|ddkr|d|dfVqdS(R)iN((R!RR((s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pys ts c3sg|]]\}}|ˆ|ksN|jˆˆƒdksN|jˆdƒdkrTdn|ˆfVqdS(iN(R (R!RR(RRRR (s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pys {scssH|]>\}}|jƒD]%}|ddkr||dfVqqdS(R)iN(tvalues(R!RtesR((s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pys ~s (RR/Rtdicttupdate(RRRR t flow_dictR7((RRRRR s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pyt_build_flow_dictds&     )R"RR c&s t||ˆˆƒ‰tdƒ‰t‡‡‡fd†tj|dtƒDƒƒ}ttˆ gd„ˆjdtƒDƒƒƒ}|ˆ kr§|t |ˆˆˆƒfSˆj }ˆj }dt t |dƒƒ} x|| dkrPxˆD] } || d} xô|| jƒD]â\} } xÓ| jƒD]Å\}}|d|d }|d | || dd kr&|d|d }|| krë|d c|7<|| | |d |d fd c|8<|| d c|8<|| d c|7>> import networkx as nx >>> G = nx.DiGraph() >>> G.add_node('a', demand = -5) >>> G.add_node('d', demand = 5) >>> G.add_edge('a', 'b', weight = 3, capacity = 4) >>> G.add_edge('a', 'c', weight = 6, capacity = 10) >>> G.add_edge('b', 'd', weight = 1, capacity = 9) >>> G.add_edge('c', 'd', weight = 2, capacity = 5) >>> flowCost, flowDict = nx.capacity_scaling(G) >>> flowCost 24 >>> flowDict # doctest: +SKIP {'a': {'c': 1, 'b': 4}, 'c': {'d': 1}, 'b': {'d': 4}, 'd': {}} It is possible to change the name of the attributes used for the algorithm. >>> G = nx.DiGraph() >>> G.add_node('p', spam = -4) >>> G.add_node('q', spam = 2) >>> G.add_node('a', spam = -2) >>> G.add_node('d', spam = -1) >>> G.add_node('t', spam = 2) >>> G.add_node('w', spam = 3) >>> G.add_edge('p', 'q', cost = 7, vacancies = 5) >>> G.add_edge('p', 'a', cost = 1, vacancies = 4) >>> G.add_edge('q', 'd', cost = 2, vacancies = 3) >>> G.add_edge('t', 'q', cost = 1, vacancies = 2) >>> G.add_edge('a', 't', cost = 2, vacancies = 4) >>> G.add_edge('d', 'w', cost = 3, vacancies = 4) >>> G.add_edge('t', 'w', cost = 4, vacancies = 1) >>> flowCost, flowDict = nx.capacity_scaling(G, demand = 'spam', ... capacity = 'vacancies', ... weight = 'cost') >>> flowCost 37 >>> flowDict # doctest: +SKIP {'a': {'t': 4}, 'd': {'w': 2}, 'q': {'d': 1}, 'p': {'q': 2, 'a': 2}, 't': {'q': 1, 'w': 1}, 'w': {}} Rc3s`|]V\}}}|jˆˆƒdksB|jˆdƒdkrHdn|ˆ|ˆVqdS(iN(R (R!RRR(RRR (s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pys sR%css"|]\}}}|dVqdS(RN((R!RRR((s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pys siiR$RR)R iR#c3s&|]}ˆj|ddkVqdS(R#iN(R(R!R(R(s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pys sssNo flow satisfying all demands.N(R5RR*R R-R.R1RR0R;RtsucctintRRtsettaddtremoveRtNonetinsertR tpoptanyR+R6(&RR"RR theapt flow_costtwmaxtR_nodestR_succtdeltaRtp_uRR7RRR)tStTtS_addtS_removetT_addtT_removeR#Rtttdtpredthth_insertth_gettd_utwminRtkmintemintd_vtd_t((RRRR s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pyRƒs¾‚  "      +&                        /      !(t__doc__t __author__t__all__t itertoolsRtmathRtnetworkxR tutilsRRRRRR5R;R(((s~/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/flow/capacityscaling.pyts   4