1+ import assert from 'assert' ;
2+
13// Adapted from http://jorisvr.nl/maximummatching.html
24// All credit for the implementation goes to Joris van Rantwijk [http://jorisvr.nl].
35
1719// to validate this new code.
1820
1921
20- export function wblossom_n3_t ( debug , CHECK_OPTIMUM , CHECK_DELTA ) {
21-
22- // If assigned, DEBUG(str) is called with lots of debug messages.
23- var DEBUG = debug ? function ( s ) { console . log ( 'DEBUG:' , s ) ; } : null ;
22+ export default function blossom ( CHECK_OPTIMUM , CHECK_DELTA ) {
2423
2524 // Check delta2/delta3 computation after every substage;
2625 // only works on integer weights, slows down the algorithm to O(n^4).
@@ -32,10 +31,6 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
3231
3332 // Compatibility
3433
35- var assert = function ( condition ) {
36- if ( ! condition ) throw new Error ( 'Assertion failed' ) ;
37- } ;
38-
3934 var min = function ( a , i , j ) {
4035
4136 var o = a [ i ] ;
@@ -284,7 +279,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
284279 // and record the fact that w was reached through the edge with
285280 // remote endpoint p.
286281 var assignLabel = function ( w , t , p ) {
287- if ( DEBUG ) DEBUG ( ' assignLabel(' + w + ',' + t + ',' + p + ')' ) ;
282+ console . debug ( ' DEBUG: assignLabel(' + w + ',' + t + ',' + p + ')' ) ;
288283 var b = inblossom [ w ] , e ;
289284 assert ( label [ w ] === 0 && label [ b ] === 0 ) ;
290285 label [ w ] = label [ b ] = t ;
@@ -293,7 +288,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
293288 if ( t === 1 ) {
294289 // b became an S-vertex/blossom; add it(s vertices) to the queue.
295290 blossomLeaves ( b , function ( e ) { queue . push ( e ) ; } ) ;
296- if ( DEBUG ) DEBUG ( ' PUSH ' + queue ) ;
291+ console . debug ( ' DEBUG: PUSH ' + queue ) ;
297292 }
298293 else if ( t === 2 ) {
299294 // b became a T-vertex/blossom; assign label S to its mate.
@@ -309,7 +304,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
309304 // Trace back from vertices v and w to discover either a new blossom
310305 // or an augmenting path. Return the base vertex of the new blossom or -1.
311306 var scanBlossom = function ( v , w ) {
312- if ( DEBUG ) DEBUG ( ' scanBlossom(' + v + ',' + w + ')' ) ;
307+ console . debug ( ' DEBUG: scanBlossom(' + v + ',' + w + ')' ) ;
313308 // Trace back from v and w, placing breadcrumbs as we go.
314309 var b , tmp , i ;
315310 var path = [ ] ;
@@ -370,7 +365,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
370365 var bw = inblossom [ w ] ;
371366 // Create blossom.
372367 var b = unusedblossoms . pop ( ) ;
373- if ( DEBUG ) DEBUG ( ' addBlossom(' + base + ',' + k + ') (v=' + v + ' w=' + w + ') -> ' + b ) ;
368+ console . debug ( ' DEBUG: addBlossom(' + base + ',' + k + ') (v=' + v + ' w=' + w + ') -> ' + b ) ;
374369 blossombase [ b ] = base ;
375370 blossomparent [ b ] = - 1 ;
376371 blossomparent [ bb ] = b ;
@@ -503,12 +498,12 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
503498 }
504499 else bestedge [ b ] = - 1 ;
505500
506- if ( DEBUG ) DEBUG ( ' blossomchilds[' + b + ']=' + blossomchilds [ b ] ) ;
501+ console . debug ( ' DEBUG: blossomchilds[' + b + ']=' + blossomchilds [ b ] ) ;
507502 } ;
508503
509504 // Expand the given top-level blossom.
510505 var expandBlossom = function ( b , endstage ) {
511- if ( DEBUG ) DEBUG ( ' expandBlossom(' + b + ',' + endstage + ') ' + blossomchilds [ b ] ) ;
506+ console . debug ( ' DEBUG: expandBlossom(' + b + ',' + endstage + ') ' + blossomchilds [ b ] ) ;
512507 // Convert sub-blossoms into top-level blossoms.
513508 var i , j , len , s , p , entrychild , jstep , endptrick , bv , stop , base ;
514509
@@ -622,7 +617,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
622617 // Swap matched/unmatched edges over an alternating path through blossom b
623618 // between vertex v and the base vertex. Keep blossom bookkeeping consistent.
624619 var augmentBlossom = function ( b , v ) {
625- if ( DEBUG ) DEBUG ( ' augmentBlossom(' + b + ',' + v + ')' ) ;
620+ console . debug ( ' DEBUG: augmentBlossom(' + b + ',' + v + ')' ) ;
626621 // Bubble up through the blossom tree from vertex v to an immediate
627622 // sub-blossom of b.
628623 var i , j , t , jstep , endptrick , stop , len , p ;
@@ -663,7 +658,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
663658 // Match the edge connecting those sub-blossoms.
664659 mate [ endpoint [ p ] ] = p ^ 1 ;
665660 mate [ endpoint [ p ^ 1 ] ] = p ;
666- if ( DEBUG ) DEBUG ( ' PAIR ' + endpoint [ p ] + ' ' + endpoint [ p ^ 1 ] + ' (k=' + Math . floor ( p / 2 ) + ')' ) ;
661+ console . debug ( ' DEBUG: PAIR ' + endpoint [ p ] + ' ' + endpoint [ p ^ 1 ] + ' (k=' + Math . floor ( p / 2 ) + ')' ) ;
667662 }
668663 // Rotate the list of sub-blossoms to put the new base at the front.
669664 rotate ( blossomchilds [ b ] , i ) ;
@@ -683,8 +678,8 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
683678 var w = edges [ k ] [ 1 ] ;
684679 var wt = edges [ k ] [ 2 ] ;
685680
686- if ( DEBUG ) DEBUG ( ' augmentMatching(' + k + ') (v=' + v + ' w=' + w + ')' ) ;
687- if ( DEBUG ) DEBUG ( ' PAIR ' + v + ' ' + w + ' (k=' + k + ')' ) ;
681+ console . debug ( ' DEBUG: augmentMatching(' + k + ') (v=' + v + ' w=' + w + ')' ) ;
682+ console . debug ( ' DEBUG: PAIR ' + v + ' ' + w + ' (k=' + k + ')' ) ;
688683
689684 [ [ v , 2 * k + 1 ] , [ w , 2 * k ] ] . forEach ( function ( e ) {
690685 var s = e [ 0 ] ;
@@ -722,7 +717,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
722717 // Keep the opposite endpoint;
723718 // it will be assigned to mate[s] in the next step.
724719 p = labelend [ bt ] ^ 1 ;
725- if ( DEBUG ) DEBUG ( ' PAIR ' + s + ' ' + t + ' (k=' + Math . floor ( p / 2 ) + ')' ) ;
720+ console . debug ( ' DEBUG: PAIR ' + s + ' ' + t + ' (k=' + Math . floor ( p / 2 ) + ')' ) ;
726721 }
727722 } ) ;
728723 } ;
@@ -801,9 +796,9 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
801796 }
802797 }
803798 }
804- if ( DEBUG && ( bestedge [ v ] !== - 1 || bk !== - 1 ) &&
799+ if ( ( bestedge [ v ] !== - 1 || bk !== - 1 ) &&
805800 ( bestedge [ v ] === - 1 || bd !== slack ( bestedge [ v ] ) ) ) {
806- DEBUG (
801+ console . debug (
807802 'v=' + v +
808803 ' bk=' + bk +
809804 ' bd=' + bd +
@@ -856,8 +851,8 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
856851 }
857852 }
858853 }
859- if ( DEBUG && bd !== tbd )
860- DEBUG ( 'bk=' + bk + ' tbk=' + tbk + ' bd=' + bd + ' tbd=' + tbd ) ;
854+ if ( bd !== tbd )
855+ console . debug ( 'bk=' + bk + ' tbk=' + tbk + ' bd=' + bd + ' tbd=' + tbd ) ;
861856 assert ( bd === tbd ) ;
862857 } ;
863858
@@ -869,7 +864,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
869864 // Each iteration of this loop is a "stage".
870865 // A stage finds an augmenting path and uses that to improve
871866 // the matching.
872- if ( DEBUG ) DEBUG ( ' STAGE ' + t ) ;
867+ console . debug ( ' DEBUG: STAGE ' + t ) ;
873868
874869 // Remove labels from top-level blossoms/vertices.
875870 i = 2 * nvertex ;
@@ -888,7 +883,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
888883
889884 // Make queue empty.
890885 queue = [ ] ;
891-
886+
892887 // Label single blossoms/vertices with S and put them in the queue.
893888 for ( v = 0 ; v < nvertex ; ++ v ) {
894889 if ( mate [ v ] === - 1 && label [ inblossom [ v ] ] === 0 )
@@ -905,15 +900,15 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
905900 // the stage ends. If there is no augmenting path, the
906901 // primal-dual method is used to pump some slack out of
907902 // the dual variables.
908- if ( DEBUG ) DEBUG ( ' SUBSTAGE') ;
903+ console . debug ( ' DEBUG: SUBSTAGE') ;
909904
910905 // Continue labeling until all vertices which are reachable
911906 // through an alternating path have got a label.
912907 while ( queue . length && ! augmented ) {
913908
914909 // Take an S vertex from the queue.
915910 v = queue . pop ( ) ;
916- if ( DEBUG ) DEBUG ( ' POP v=' + v ) ;
911+ console . debug ( ' DEBUG: POP v=' + v ) ;
917912 assert ( label [ inblossom [ v ] ] === 1 ) ;
918913
919914 // Scan its neighbours:
@@ -1077,7 +1072,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
10771072 }
10781073
10791074 // Take action at the point where minimum delta occurred.
1080- if ( DEBUG ) DEBUG ( ' delta' + deltatype + '=' + delta ) ;
1075+ console . debug ( ' DEBUG: delta' + deltatype + '=' + delta ) ;
10811076 if ( deltatype === 1 ) {
10821077 // No further improvement possible; optimum reached.
10831078 break ;
0 commit comments