@@ -72,6 +72,7 @@ public static HashSet<Payment> CalculateBestSettleOptions(Group group, List<Tran
7272
7373 graph . EliminateLoops ( ) ;
7474 graph . EliminateSplits ( ) ;
75+ graph . EliminateChains ( ) ;
7576
7677 return graph . ToPayments ( ) ;
7778 }
@@ -123,23 +124,6 @@ public void AddEdge(Member source, Member destination, decimal amount)
123124 sourceNode . Edges [ destinationNode ] = amount ;
124125 }
125126
126- public string ToGraphviz ( )
127- {
128- var sb = new StringBuilder ( ) ;
129- sb . AppendLine ( "digraph G {" ) ;
130-
131- foreach ( var node in _nodes )
132- {
133- foreach ( var ( destination , amount ) in node . Edges )
134- {
135- sb . AppendLine ( $ " \" { node . Person . Name } \" -> \" { destination . Person . Name } \" [label=\" { amount } \" ];") ;
136- }
137- }
138-
139- sb . AppendLine ( "}" ) ;
140- return sb . ToString ( ) ;
141- }
142-
143127 public void EliminateSplits ( )
144128 {
145129 foreach ( var node in _nodes )
@@ -177,7 +161,7 @@ private bool EliminateSplitBFS(Node start)
177161 return false ;
178162 }
179163
180- private void RemoveFoundSplit ( Node shorterRouteWithFinalNode , Node longerRoute , decimal fromLongerToFinal )
164+ private static void RemoveFoundSplit ( Node shorterRouteWithFinalNode , Node longerRoute , decimal fromLongerToFinal )
181165 {
182166 HashSet < Node > longerRouteNodes = [ ] ;
183167
@@ -267,7 +251,6 @@ private bool EliminateLoopDFS(Node currentNode, HashSet<Node> visited)
267251 if ( visited . Contains ( edge . Key ) )
268252 {
269253 RemoveFoundLoop ( currentNode ) ;
270- var deez = ToGraphviz ( ) ;
271254 return true ;
272255 }
273256 visited . Add ( currentNode ) ;
@@ -317,6 +300,59 @@ private static void RemoveFoundLoop(Node currentNode)
317300 currentNode . Edges . Remove ( currentNodeSuccessor ) ;
318301 }
319302 }
303+
304+ public void EliminateChains ( )
305+ {
306+ while ( true )
307+ {
308+ var changed = false ;
309+
310+ foreach ( var u in _nodes . ToList ( ) )
311+ {
312+ foreach ( var uvPair in u . Edges . ToList ( ) )
313+ {
314+ var v = uvPair . Key ;
315+ var uvValue = uvPair . Value ;
316+ if ( uvValue <= 0 )
317+ {
318+ continue ;
319+ }
320+
321+ foreach ( var vwPair in v . Edges . ToList ( ) )
322+ {
323+ var w = vwPair . Key ;
324+ var vwValue = vwPair . Value ;
325+ if ( w == u )
326+ {
327+ continue ;
328+ }
329+
330+ if ( Math . Abs ( uvValue - vwValue ) <= 0.0000001m )
331+ {
332+ u . Edges . Remove ( v ) ;
333+ v . Edges . Remove ( w ) ;
334+
335+ if ( u . Edges . TryGetValue ( w , out var uw ) )
336+ {
337+ u . Edges [ w ] = uw + uvValue ;
338+ }
339+ else
340+ {
341+ u . Edges [ w ] = uvValue ;
342+ }
343+
344+ changed = true ;
345+ break ;
346+ }
347+ }
348+ if ( changed ) break ;
349+ }
350+ if ( changed ) break ;
351+ }
352+ if ( ! changed ) break ;
353+ }
354+ RemovePredecesors ( ) ;
355+ }
320356 }
321357
322358 private class Node
0 commit comments