INLINE_IF_HEADER_ONLY void MorseDecomposition:: assign ( Digraph const& digraph, Components const& components ) { data_ . reset ( new MorseDecomposition_ ); data_ -> components_ = components; uint64_t C = components . size (); uint64_t R = components . recurrentComponents () . size (); std::vector<std::vector<uint64_t>> reachability ( R ); std::vector<uint64_t> recurrent_indices; for ( uint64_t i = 0; i < C; ++ i ) { if ( components . isRecurrent ( i ) ) { recurrent_indices . push_back ( i ); } } // Proceed in cohorts of 64 recurrent components. There are ceil(R/64) cohorts uint64_t num_cohorts = R / 64; if ( R % 64 != 0 ) ++ num_cohorts; // Round up for ceiling std::vector<uint64_t> reach_info ( C, 0 ); for ( uint64_t cohort = 0; cohort < num_cohorts; ++ cohort ) { if ( cohort > 0 ) std::fill ( reach_info.begin(), reach_info.end(), 0); uint64_t source = 64LL*cohort; // Give each recurrent component in the cohort a unique bit signature // e.g. the 5th component gets 000...00010000 for ( uint64_t i = 0; i < 64; ++ i, ++ source ) { if ( source == R ) break; reach_info [ recurrent_indices [ source ] ] = (1LL << i); } // Propagate reachability information by bitwise-oring bit signatures uint64_t parent_comp = 0; for ( auto const& component : components ) { for ( uint64_t u : component ) { std::vector<uint64_t> const& children = digraph . adjacencies ( u ); for ( uint64_t v : children ) { uint64_t child_comp = components . whichComponent ( v ); reach_info [ child_comp ] |= reach_info [ parent_comp ]; } } ++ parent_comp; } for ( uint64_t i = 0; i < R; ++ i ) { uint64_t code = reach_info [ recurrent_indices [ i ] ]; uint64_t ancestor = 64*cohort; while ( code != 0 ) { if ( code & 1 ) reachability[ancestor].push_back(i); code >>= 1; ++ ancestor; } } } data_ -> poset_ = Poset(reachability); _canonicalize (); }
void wbpcover ( int n_left, /* number of vertices on left side */ int n_right, /* number of vertices on right side */ int *pointers, /* start/stop of adjacency lists */ int *indices, /* adjacency list for each vertex */ int *vweight, /* vertex weights */ int *psep_size, /* returned size of separator */ int *psep_weight, /* returned weight of separator */ int **psep_nodes /* list of separator nodes */ ) { extern int DEBUG_COVER; /* debug flag for this routine */ int *touched; /* flags for each vertex */ int *resid; /* remaining, unmatched vertex weight */ int *flow; /* flow on each right->left edge */ int *sep_nodes; /* list of separator nodes */ int sep_size; /* returned size of separator */ int sep_weight; /* returned weight of separator */ int nedges; /* number of edges in bipartite graph */ int i, j; /* loop counter */ int wleft, wright, wedges; void confirm_cover(); if (DEBUG_COVER) { printf("-> Entering wbpcover, nleft = %d, nright = %d, 2*nedges = %d\n", n_left, n_right, pointers[n_left+n_right]-pointers[0]); wleft = wright = 0; wedges = 0; for (i = 0; i < n_left; i++) { wleft += vweight[i]; for (j = pointers[i]; j < pointers[i + 1]; j++) { wedges += vweight[i] * vweight[indices[j]]; } } for (i = n_left; i < n_left + n_right; i++) { wright += vweight[i]; for (j = pointers[i]; j < pointers[i + 1]; j++) { wedges += vweight[i] * vweight[indices[j]]; } } printf(" Corresponds to unweighted, nleft = %d, nright = %d, 2*nedges = %d\n", wleft, wright, wedges); } nedges = pointers[n_left + n_right] - pointers[0]; resid = smalloc((n_left + n_right) * sizeof(int)); touched = smalloc((n_left + n_right) * sizeof(int)); flow = smalloc((nedges + 1) * sizeof(int)); /* Not a matching. I can be connected to multiple nodes. */ bpflow(n_left, n_right, pointers, indices, vweight, resid, flow, touched); reachability(n_left, n_right, pointers, indices, resid, flow, touched); /* Separator includes untouched nodes on left, touched on right. */ /* Left separator nodes if unconnected to unmatched right node via */ /* augmenting path, right separator nodes otherwise. */ /* First count the separator size for malloc. */ sep_size = 0; for (i = 0; i < n_left; i++) { if (!touched[i]) { sep_size++; } } for (i = n_left; i < n_left + n_right; i++) { if (touched[i]) { sep_size++; } } sep_nodes = smalloc((sep_size + 1) * sizeof(int)); sep_size = sep_weight = 0; for (i = 0; i < n_left; i++) { if (!touched[i]) { sep_nodes[sep_size++] = i; sep_weight += vweight[i]; } } for (i = n_left; i < n_left + n_right; i++) { if (touched[i]) { sep_nodes[sep_size++] = i; sep_weight += vweight[i]; } } sep_nodes[sep_size] = 0; *psep_size = sep_size; *psep_weight = sep_weight; *psep_nodes = sep_nodes; /* Check the answer. */ if (DEBUG_COVER) { confirm_cover(n_left, n_right, pointers, indices, flow, vweight, resid, sep_size, sep_nodes); } sfree(flow); sfree(touched); sfree(resid); }
// What are the specified player's next possible moves LocationID *whereCanTheyGo(DracView currentView, int *numLocations, PlayerID player, int road, int rail, int sea) { assert(currentView != NULL); assert(player >= PLAYER_LORD_GODALMING && player <= PLAYER_DRACULA); assert(numLocations != NULL); LocationID from = currentView->playerstate[player]->current; assert(from >= ALICANTE && from < NUM_MAP_LOCATIONS); Round round = currentView->gameturn; assert(round >= 0 && round <= 366); Map europe = newMap(); LocationID locations[NUM_MAP_LOCATIONS]; int i,j=0; //USE AN ARRAY TO INDICATE PATHING TO EVERY DESTINATION //0 -> cannot reach, 1 -> reachable for ( i=0; i<NUM_MAP_LOCATIONS; i++ ) { locations[i] = 0; } //The reachability will mark on the array if ( road ) { reachability(europe, from, ROAD, ONEPATH, locations); } if ( rail && player != PLAYER_DRACULA) { //Dracula can't travel by rail int roundmod = (round+player) % 4; reachability(europe, from, RAIL, roundmod, locations); } if (sea) { reachability(europe, from, BOAT, ONEPATH, locations); } //PATH FIXING FOR DRACULA if ( player == PLAYER_DRACULA ) { //Dracula can't move to hospital, this is a incorrect path. locations[ST_JOSEPH_AND_ST_MARYS] = 0; //checks if Dracula is allowed to hide //check for hide in trail while( i<TRAIL_SIZE ){ if( currentView->playerstate[PLAYER_DRACULA]->trail[i] == HIDE ){ locations[from] = 0; } } //check if at sea if( idToType(from) == SEA ); locations[from] = 0; } //place reachable locations into our return array j = 0; LocationID *reachable = malloc(sizeof (int)*NUM_MAP_LOCATIONS); //place corresponding cities (e.g. ALICANTE, ROME, MARSEILLES) into 'result' for (i=0; i<NUM_MAP_LOCATIONS; i++) { if ( locations[i] ) { reachable[j] = i; j++; } } *numLocations = j; destroyMap(europe); return reachable; }