1
+ import assert from 'assert' ;
2
+
1
3
// Adapted from http://jorisvr.nl/maximummatching.html
2
4
// All credit for the implementation goes to Joris van Rantwijk [http://jorisvr.nl].
3
5
17
19
// to validate this new code.
18
20
19
21
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 ) {
24
23
25
24
// Check delta2/delta3 computation after every substage;
26
25
// 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) {
32
31
33
32
// Compatibility
34
33
35
- var assert = function ( condition ) {
36
- if ( ! condition ) throw new Error ( 'Assertion failed' ) ;
37
- } ;
38
-
39
34
var min = function ( a , i , j ) {
40
35
41
36
var o = a [ i ] ;
@@ -284,7 +279,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
284
279
// and record the fact that w was reached through the edge with
285
280
// remote endpoint p.
286
281
var assignLabel = function ( w , t , p ) {
287
- if ( DEBUG ) DEBUG ( ' assignLabel(' + w + ',' + t + ',' + p + ')' ) ;
282
+ console . debug ( ' DEBUG: assignLabel(' + w + ',' + t + ',' + p + ')' ) ;
288
283
var b = inblossom [ w ] , e ;
289
284
assert ( label [ w ] === 0 && label [ b ] === 0 ) ;
290
285
label [ w ] = label [ b ] = t ;
@@ -293,7 +288,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
293
288
if ( t === 1 ) {
294
289
// b became an S-vertex/blossom; add it(s vertices) to the queue.
295
290
blossomLeaves ( b , function ( e ) { queue . push ( e ) ; } ) ;
296
- if ( DEBUG ) DEBUG ( ' PUSH ' + queue ) ;
291
+ console . debug ( ' DEBUG: PUSH ' + queue ) ;
297
292
}
298
293
else if ( t === 2 ) {
299
294
// 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) {
309
304
// Trace back from vertices v and w to discover either a new blossom
310
305
// or an augmenting path. Return the base vertex of the new blossom or -1.
311
306
var scanBlossom = function ( v , w ) {
312
- if ( DEBUG ) DEBUG ( ' scanBlossom(' + v + ',' + w + ')' ) ;
307
+ console . debug ( ' DEBUG: scanBlossom(' + v + ',' + w + ')' ) ;
313
308
// Trace back from v and w, placing breadcrumbs as we go.
314
309
var b , tmp , i ;
315
310
var path = [ ] ;
@@ -370,7 +365,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
370
365
var bw = inblossom [ w ] ;
371
366
// Create blossom.
372
367
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 ) ;
374
369
blossombase [ b ] = base ;
375
370
blossomparent [ b ] = - 1 ;
376
371
blossomparent [ bb ] = b ;
@@ -503,12 +498,12 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
503
498
}
504
499
else bestedge [ b ] = - 1 ;
505
500
506
- if ( DEBUG ) DEBUG ( ' blossomchilds[' + b + ']=' + blossomchilds [ b ] ) ;
501
+ console . debug ( ' DEBUG: blossomchilds[' + b + ']=' + blossomchilds [ b ] ) ;
507
502
} ;
508
503
509
504
// Expand the given top-level blossom.
510
505
var expandBlossom = function ( b , endstage ) {
511
- if ( DEBUG ) DEBUG ( ' expandBlossom(' + b + ',' + endstage + ') ' + blossomchilds [ b ] ) ;
506
+ console . debug ( ' DEBUG: expandBlossom(' + b + ',' + endstage + ') ' + blossomchilds [ b ] ) ;
512
507
// Convert sub-blossoms into top-level blossoms.
513
508
var i , j , len , s , p , entrychild , jstep , endptrick , bv , stop , base ;
514
509
@@ -622,7 +617,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
622
617
// Swap matched/unmatched edges over an alternating path through blossom b
623
618
// between vertex v and the base vertex. Keep blossom bookkeeping consistent.
624
619
var augmentBlossom = function ( b , v ) {
625
- if ( DEBUG ) DEBUG ( ' augmentBlossom(' + b + ',' + v + ')' ) ;
620
+ console . debug ( ' DEBUG: augmentBlossom(' + b + ',' + v + ')' ) ;
626
621
// Bubble up through the blossom tree from vertex v to an immediate
627
622
// sub-blossom of b.
628
623
var i , j , t , jstep , endptrick , stop , len , p ;
@@ -663,7 +658,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
663
658
// Match the edge connecting those sub-blossoms.
664
659
mate [ endpoint [ p ] ] = p ^ 1 ;
665
660
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 ) + ')' ) ;
667
662
}
668
663
// Rotate the list of sub-blossoms to put the new base at the front.
669
664
rotate ( blossomchilds [ b ] , i ) ;
@@ -683,8 +678,8 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
683
678
var w = edges [ k ] [ 1 ] ;
684
679
var wt = edges [ k ] [ 2 ] ;
685
680
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 + ')' ) ;
688
683
689
684
[ [ v , 2 * k + 1 ] , [ w , 2 * k ] ] . forEach ( function ( e ) {
690
685
var s = e [ 0 ] ;
@@ -722,7 +717,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
722
717
// Keep the opposite endpoint;
723
718
// it will be assigned to mate[s] in the next step.
724
719
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 ) + ')' ) ;
726
721
}
727
722
} ) ;
728
723
} ;
@@ -801,9 +796,9 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
801
796
}
802
797
}
803
798
}
804
- if ( DEBUG && ( bestedge [ v ] !== - 1 || bk !== - 1 ) &&
799
+ if ( ( bestedge [ v ] !== - 1 || bk !== - 1 ) &&
805
800
( bestedge [ v ] === - 1 || bd !== slack ( bestedge [ v ] ) ) ) {
806
- DEBUG (
801
+ console . debug (
807
802
'v=' + v +
808
803
' bk=' + bk +
809
804
' bd=' + bd +
@@ -856,8 +851,8 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
856
851
}
857
852
}
858
853
}
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 ) ;
861
856
assert ( bd === tbd ) ;
862
857
} ;
863
858
@@ -869,7 +864,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
869
864
// Each iteration of this loop is a "stage".
870
865
// A stage finds an augmenting path and uses that to improve
871
866
// the matching.
872
- if ( DEBUG ) DEBUG ( ' STAGE ' + t ) ;
867
+ console . debug ( ' DEBUG: STAGE ' + t ) ;
873
868
874
869
// Remove labels from top-level blossoms/vertices.
875
870
i = 2 * nvertex ;
@@ -888,7 +883,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
888
883
889
884
// Make queue empty.
890
885
queue = [ ] ;
891
-
886
+
892
887
// Label single blossoms/vertices with S and put them in the queue.
893
888
for ( v = 0 ; v < nvertex ; ++ v ) {
894
889
if ( mate [ v ] === - 1 && label [ inblossom [ v ] ] === 0 )
@@ -905,15 +900,15 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
905
900
// the stage ends. If there is no augmenting path, the
906
901
// primal-dual method is used to pump some slack out of
907
902
// the dual variables.
908
- if ( DEBUG ) DEBUG ( ' SUBSTAGE') ;
903
+ console . debug ( ' DEBUG: SUBSTAGE') ;
909
904
910
905
// Continue labeling until all vertices which are reachable
911
906
// through an alternating path have got a label.
912
907
while ( queue . length && ! augmented ) {
913
908
914
909
// Take an S vertex from the queue.
915
910
v = queue . pop ( ) ;
916
- if ( DEBUG ) DEBUG ( ' POP v=' + v ) ;
911
+ console . debug ( ' DEBUG: POP v=' + v ) ;
917
912
assert ( label [ inblossom [ v ] ] === 1 ) ;
918
913
919
914
// Scan its neighbours:
@@ -1077,7 +1072,7 @@ export function wblossom_n3_t (debug, CHECK_OPTIMUM, CHECK_DELTA) {
1077
1072
}
1078
1073
1079
1074
// Take action at the point where minimum delta occurred.
1080
- if ( DEBUG ) DEBUG ( ' delta' + deltatype + '=' + delta ) ;
1075
+ console . debug ( ' DEBUG: delta' + deltatype + '=' + delta ) ;
1081
1076
if ( deltatype === 1 ) {
1082
1077
// No further improvement possible; optimum reached.
1083
1078
break ;
0 commit comments