void bfs(edge_index_t *edge_begin, edge_index_t *edge_end, node_index_t *dst, node_index_t starting_node, level_t *level, edge_index_t *level_counts) { node_index_t queue[N_NODES]; node_index_t q_in, q_out; node_index_t dummy; node_index_t n; edge_index_t e; /*init_levels: for( n=0; n<N_NODES; n++ )*/ /*level[n] = MAX_LEVEL;*/ /*init_horizons: for( i=0; i<N_LEVELS; i++ )*/ /*level_counts[i] = 0;*/ q_in = 1; q_out = 0; level[starting_node] = 0; level_counts[0] = 1; Q_PUSH(starting_node); loop_queue: for( dummy=0; dummy<N_NODES; dummy++ ) { // Typically while(not_empty(queue)){ if( Q_EMPTY() ) break; n = Q_PEEK(); Q_POP(); edge_index_t tmp_begin = edge_begin[n]; edge_index_t tmp_end = edge_end[n]; loop_neighbors: for( e=tmp_begin; e<tmp_end; e++ ) { node_index_t tmp_dst = dst[e]; level_t tmp_level = level[tmp_dst]; if( tmp_level ==MAX_LEVEL ) { // Unmarked level_t tmp_level = level[n]+1; level[tmp_dst] = tmp_level; ++level_counts[tmp_level]; Q_PUSH(tmp_dst); } } } /* printf("Horizons:"); for( i=0; i<N_LEVELS; i++ ) printf(" %d", level_counts[i]); printf("\n"); */ }
/* schedule: adds a given symbol to the appropriate queue depending upon its type. Formulae are added to the formula queue; actions are added to the action queue if they have sources (ie if it is a "triggered action" -- proc p:v {} is a triggered action, proc p {} is not); other types are ignored. If it is already in the queue, then move it to the end, so duplicates do not appear. This rule does not apply in dtkeden if synchronize is on. In this case, we may want to faithfully enact each redefinition, as they may be coming from another machine, even if we have not managed to finish evaluating the queue yet. Hence duplicates are allowed in this case. [Ash] */ static void schedule(symptr sp) { register symptr_ATOM P; register symptr_QUEUE *Q; #ifdef DISTRIB extern Int *synchronize; #endif /* DISTRIB */ switch (sp->stype) { case FORMULA: DEBUGPRINT("FQUEUE schedule %s\n", sp->name); Q = &formula_queue; break; case BLTIN: case PROCEDURE: case FUNCTION: case PROCMACRO: DEBUGPRINT("AQUEUE schedule %s\n", sp->name); Q = &action_queue; break; default: /* If VAR, for example */ DEBUGPRINT2("schedule: not scheduling %s %s\n", typename(sp->stype), sp->name); return; /* don't queue up */ } /* if (P = SEARCH_symptr(Q, sp, 1)) { */ #ifdef DISTRIB if ((P = sp->Qloc) && !*synchronize) /* This may raise a problem in a distributed or synchronized environment, because some information will be missed. For example, if we want to make a train move smoothly, we need to show every slight move. But this reschedule may make previous movements disappear. So we take synchronization into account --sun */ #else if ((P = sp->Qloc)) #endif /* not DISTRIB */ { /* Already there --> reschedule */ DELETE_ATOM(Q, P); APPEND_Q(Q, P); } else { /* Not there --> put it at the end */ switch (sp->stype) { case FORMULA: APPEND_symptr_Q(Q, sp); sp->Qloc = Q->prev; break; case BLTIN: case PROCEDURE: case PROCMACRO: case FUNCTION: /* if it's an action */ if (!Q_EMPTY(&sp->sources)) { APPEND_symptr_Q(Q, sp); sp->Qloc = Q->prev; } break; } } }