/* * See Figure 10-3, "The bipartite matching algorithm", page 224. * * Corresponds to "procedure augment(v)", * but is iterative instead of recursive. */ static void hm_augment( hm_data *hm, int v ) { while ( LABEL( v ) != blank ) { EXPOSED( LABEL( v ) ) = MATE( v ); MATE( v ) = EXPOSED( v ); MATE( EXPOSED( v ) ) = v; v = LABEL( v ); } MATE( v ) = EXPOSED( v ); MATE( EXPOSED( v ) ) = v; }
/* * See Figure 11-2, "The Hungarian method", page 251. * * Corresponds to lines 12--17. */ static void hm_construct_auxiliary_graph( hm_data *hm ) { int i, j; A.size = 0; for EACH_V( i ) { EXPOSED( i ) = blank; LABEL( i ) = blank; /* * The following data structure is not included in the Figure 11-2 * pseudo-code implementation. It has been added to account for * "labeling" on certain vertices described within Example 11.1 that * would otherwise be missing from the Figure 11-2 implementation. * * count[v] for any v \in V is equal to the size of the set * { u \in U : nhbor[u] = v }. When this set is non-empty, v is * considered to be "labeled". The use of this new data structure is * only to complete the conditional check on "labeled" statuses when * updating alpha within "procedure modify". */ COUNT( i ) = 0; } for EACH_U( j ) { SLACK( j ) = INT_MAX; /* * The following initialization of nhbor[] is necessary for proper usage * of the count[] array, whose addition and purpose is described above. */ NHBOR( j ) = blank; } for EACH_V( i ) { for EACH_U( j ) { if ( ALPHA( i ) + BETA( j ) == C( i, j ) ) { if ( MATE( j ) == blank ) { EXPOSED( i ) = j; } else if ( i != MATE( j ) ) { add_arc( &A, i, MATE( j ) ); } } } } }
/* * See Figure 11-2, "The Hungarian method", page 251. * * Corresponds to lines 29--41. */ static bool hm_search( hm_data *hm ) { int i, j, z; while ( Q.size != 0 ) { i = stack_pop( &Q ); for ( z = 0; z < A.size; ++z ) { if ( A.data[ z ].x == i ) { j = A.data[ z ].y; if ( LABEL( j ) == blank ) { LABEL( j ) = i; if ( EXPOSED( j ) != blank ) { hm_augment( hm, j ); return false; /* goto endstage */ } /* * The following instruction is listed just before the prior * conditional in Figure 11-2. Here, it is relocated simply * because its execution would serve no purpose if the prior * conditional executes. */ stack_push( &Q, j ); hm_update_slack( hm, j ); } } } } return true; }
/* * This function is for debugging purposes. It prints the algorithm's internal * state in a format similar to that of Example 11.1 (The matrix form of the * Hungarian method) beginning on page 252. * * The formatted output coded here is intended for small numbers. */ static void hm_print( hm_data *hm ) { int i, j, k; printf( "\n a\\b |" ); for EACH_U( j ) { printf( "%3d ", BETA( j ) ); } printf( "mate exposed label\n" ); printf( "-----+" ); for EACH_U( j ) { printf( "----" ); } printf( "------------------\n" ); for EACH_V( i ) { printf( " |\n %3d |", ALPHA( i ) ); for EACH_U( j ) { printf( "%3d ", C( i, j ) ); } printf( "%4d %7d %5d\n", MATE( i ), EXPOSED( i ), LABEL( i ) ); } printf( "\nslack" ); for EACH_U( j ) { printf( " %3d", SLACK( j ) == INT_MAX ? -1 : SLACK( j ) ); } printf( "\nnhbor" ); for EACH_U( j ) { printf( " %3d", NHBOR( j ) ); } printf( "\n\nA = { " ); for ( k = 0; k < A.size; ++k ) { printf( "(%d,%d) ", A.data[ k ].x, A.data[ k ].y ); } printf( "}\nQ = { " ); for ( k = 0; k < Q.size; ++k ) { printf( "%d ", Q.data[ k ] ); } printf( "}\n\n" ); }
/* * See Figure 11-2, "The Hungarian method", page 251. * * Corresponds to lines 19--28. */ static bool hm_pre_search( hm_data *hm ) { int i; Q.size = 0; for EACH_V( i ) { if ( MATE( i ) == blank ) { if ( EXPOSED( i ) != blank ) { hm_augment( hm, i ); return false; /* goto endstage */ } stack_push( &Q, i ); LABEL( i ) = blank; hm_update_slack( hm, i ); } } return true; }
/* * See Figure 11-2, "The Hungarian method", page 252. * * Corresponds to "procedure modify". */ static bool hm_modify( hm_data *hm ) { int i, j, theta_one; /* * Determine theta_one. */ theta_one = INT_MAX; for EACH_U( j ) { if ( 0 < SLACK( j ) && SLACK( j ) < theta_one ) { theta_one = SLACK( j ); } } theta_one /= 2; /* * Update the dual variable alpha. */ for EACH_V( i ) { /* * The following conditional expression has been changed from its form * in Figure 11-2. Here, an additional check on the count[] array is * performed to account for a certain type of "labeling" that is * mentioned in the Example 11.1 walk-through but is omitted from the * Figure 11-2 implementation. * * See the comments provided near the initialization of count[] in the * function hm_construct_auxiliary_graph(). */ if ( LABEL( i ) != blank || COUNT( i ) > 0 ) { ALPHA( i ) += theta_one; } else { ALPHA( i ) -= theta_one; } } /* * Update the dual variable beta. */ for EACH_U( j ) { if ( SLACK( j ) == 0 ) { BETA( j ) -= theta_one; } else { BETA( j ) += theta_one; } } /* * Update slack and check for new admissible edges. */ for EACH_U( j ) { if ( SLACK( j ) > 0 ) { SLACK( j ) -= 2 * theta_one; if ( SLACK( j ) == 0 ) { if ( MATE( j ) == blank ) { EXPOSED( NHBOR( j ) ) = j; hm_augment( hm, NHBOR( j ) ); return false; /* goto endstage */ } else { /* * The following statement corresponds to a pseudo-code * command that should be removed from the else-clause of * the modify procedure in Figure 11-2. * * LABEL( MATE( j ) ) = NHBOR( j ); * * The inclusion of the above statement causes the arc * added in one of the next statements to never be considered * in following "search" sub-stages during this stage, and it * partially duplicates what would happen in these sub-stages * if the arc were to be considered there. The result of * inclusion is (often) non-optimality of the algorithm's * output. */ /* * The next statement corresponds to a pseudo-code command * (in the same else-clause) that should be modified * slightly. In Figure 11-2, this command "pushes" mate[ u ] * into Q when it should be "pushing" nhbor[ u ] instead. * This is because the purpose of this command is to ensure * that the soon-to-be-added arc will be considered in the * next "search" sub-stage, and consideration is dependent * upon the arc-tail, not the arc-head. */ stack_push( &Q, NHBOR( j ) ); /* Note modification */ add_arc( &A, NHBOR( j ), MATE( j ) ); } } } } return true; }
bool Board::isCovered(int row, int column) { return ! EXPOSED(row, column); }