/** * Determine if no points are found * * @return True if no points added */ bool empty() const { return m_q.empty(); }
inline T get() { T best_item = elements.top().second; elements.pop(); return best_item; }
tripoint get_next() { auto pt = open.top(); open.pop(); return pt.second; }
inline bool empty(void) const { return data.empty(); }
inline bool empty() { return elements.empty(); }
void AggregatingSortedBlockInputStream::merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue) { size_t merged_rows = 0; /// We take the rows in the correct order and put them in `merged_block`, while the rows are no more than `max_block_size` while (!queue.empty()) { SortCursor current = queue.top(); setPrimaryKeyRef(next_key, current); bool key_differs; if (current_key.empty()) /// The first key encountered. { setPrimaryKeyRef(current_key, current); key_differs = true; } else key_differs = next_key != current_key; /// if there are enough rows accumulated and the last one is calculated completely if (key_differs && merged_rows >= max_block_size) return; queue.pop(); if (key_differs) { current_key.swap(next_key); /// We will write the data for the group. We copy the values of ordinary columns. for (size_t i = 0, size = column_numbers_not_to_aggregate.size(); i < size; ++i) { size_t j = column_numbers_not_to_aggregate[i]; merged_columns[j]->insertFrom(*current->all_columns[j], current->pos); } /// Add the empty aggregation state to the aggregate columns. The state will be updated in the `addRow` function. for (auto & column_to_aggregate : columns_to_aggregate) column_to_aggregate->insertDefault(); ++merged_rows; } addRow(current); if (!current->isLast()) { current->next(); queue.push(current); } else { /// We fetch the next block from the appropriate source, if there is one. fetchNextBlock(current, queue); } } finished = true; }
void AddToHeaps(std::priority_queue<double, std::vector<double>, std::greater<double> >& m, std::priority_queue<double>& M, double x){ // decide on initial heap to place element into if(m.empty() || x < m.top()) M.push(x); else m.push(x); // make sure that heaps are balanced if(m.size() > M.size() + 1){ M.push( m.top() ); m.pop(); } else if(M.size() > m.size() + 1){ m.push( M.top() ); M.pop(); } }
void checkCollision() { int i, j; if ( events.size()!=0) { while( elapsedTime >= events.top().timeOccuring) { i = events.top().i; if( checkOutdated( events.top() ) ) { printf("---POOPZIES of %d, timeInserted=%f, lastCollition=%f\n", i, events.top().timeInserted, sphere[i].lastCollision ); events.pop(); } else if (events.top().j!=-1) { j = events.top().j; sphere[i].q0 += (events.top().timeOccuring - sphere[i].t0) * sphere[i].speedVec; sphere[i].speedVec = sphere[i].newSpeedVec; sphere[i].t0 = events.top().timeOccuring; sphere[j].q0 += (events.top().timeOccuring - sphere[j].t0) * sphere[j].speedVec; sphere[j].speedVec = sphere[j].newSpeedVec; sphere[j].t0 = events.top().timeOccuring; sphere[i].cols++; sphere[j].cols++; events.pop(); calculateCollision(i); calculateCollision(j); printf("BALLZIES of %d, timeInserted=%f, lastCollition=%f\n", i, events.top().timeInserted, sphere[i].lastCollision ); } else { sphere[i].q0 += (events.top().timeOccuring - sphere[i].t0) * sphere[i].speedVec; sphere[i].speedVec = sphere[i].newSpeedVec; sphere[i].t0 = events.top().timeOccuring; sphere[i].cols++; events.pop(); calculateCollision(i); printf("WALLZIES of %d, timeInserted=%f, lastCollition=%f\n", i, events.top().timeInserted, sphere[i].lastCollision ); } } //std::vector<Sphere>::iterator it = sphereIterInit; //for(it; it != sphere.end();it++){ // position = it->q0 + (float)(elapsedTime - it->t0) * it->speedVec; // if(abs(position.x)>0.96f || abs(position.y)>0.96f || abs(position.z)>0.96f){ // printf("WHAT THE F**K MOAR BUGS PLS!!!!!AAAAAAAAAAARRGGH\n"); // } //} minmin = (events.top().timeOccuring<minmin)?events.top().timeOccuring:minmin; } }
void pop() { _pq.pop(); }
Cell top() const { return _pq.top().cell; }
void dijkstra_pq_thread(CSRGraph *g, int *dist, std::priority_queue<Priority_struct, std::vector<Priority_struct>, Compare_priority> &pq, int threadNum, std::mutex *dist_locks) { while(!pq.empty()) { queue_lock.lock(); if(pq.empty()) { queue_lock.unlock(); break; } Priority_struct temp_struct = pq.top(); int u = temp_struct.node_name; pq.pop(); printf("Popped\n"); for(int i=0; i< pq.size();i++){ printf(" %d", pq[i]); } printf("\n"); int udist = dist[u]; queue_lock.unlock(); std::vector<int> neighbors = CSRGraph_getNeighbors(g, u); int neighbor; for(neighbor=0;neighbor < neighbors.size(); neighbor++) { int v = neighbors[neighbor]; int uvdist = CSRGraph_getDistance(g, u, v); int alt = udist + uvdist; dist_locks[v].lock(); if(alt < dist[v]) { dist[v] = alt; dist_locks[v].unlock(); Priority_struct temp2; temp2.node_name=v; temp2.node_weight = uvdist; queue_lock.lock(); pq.push(temp2); printf("Pushed\n"); for(int i=0; i< pq.size();i++){ printf(" %d", pq[i]); } printf("\n"); queue_lock.unlock(); } else { dist_locks[v].unlock(); } } } //printf("Thread %d ended.\n", threadNum); }
void push(Cell const& cell, Value const& value) { _pq.push(Entry(cell, value, ++_count)); }
void MergingSortedBlockInputStream::merge(Block & merged_block, ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue) { size_t merged_rows = 0; /** Увеличить счётчики строк. * Вернуть true, если пора закончить формировать текущий блок данных. */ auto count_row_and_check_limit = [&, this]() { ++total_merged_rows; if (limit && total_merged_rows == limit) { // std::cerr << "Limit reached\n"; cancel(); finished = true; return true; } ++merged_rows; if (merged_rows == max_block_size) { // std::cerr << "max_block_size reached\n"; return true; } return false; }; /// Вынимаем строки в нужном порядке и кладём в merged_block, пока строк не больше max_block_size while (!queue.empty()) { TSortCursor current = queue.top(); queue.pop(); while (true) { /** А вдруг для текущего курсора блок целиком меньше или равен, чем остальные? * Или в очереди остался только один источник данных? Тогда можно целиком взять блок текущего курсора. */ if (current.impl->isFirst() && (queue.empty() || current.totallyLessOrEquals(queue.top()))) { // std::cerr << "current block is totally less or equals\n"; /// Если в текущем блоке уже есть данные, то сначала вернём его. Мы попадём сюда снова при следующем вызове функции merge. if (merged_rows != 0) { // std::cerr << "merged rows is non-zero\n"; queue.push(current); return; } /// Actually, current.impl->order stores source number (i.e. cursors[current.impl->order] == current.impl) size_t source_num = current.impl->order; if (source_num >= cursors.size()) throw Exception("Logical error in MergingSortedBlockInputStream", ErrorCodes::LOGICAL_ERROR); for (size_t i = 0; i < num_columns; ++i) merged_block.getByPosition(i).column = source_blocks[source_num]->getByPosition(i).column; // std::cerr << "copied columns\n"; size_t merged_rows = merged_block.rows(); if (limit && total_merged_rows + merged_rows > limit) { merged_rows = limit - total_merged_rows; for (size_t i = 0; i < num_columns; ++i) { auto & column = merged_block.getByPosition(i).column; column = column->cut(0, merged_rows); } cancel(); finished = true; } if (out_row_sources) out_row_sources->resize_fill(out_row_sources->size() + merged_rows, RowSourcePart(source_num)); // std::cerr << "fetching next block\n"; total_merged_rows += merged_rows; fetchNextBlock(current, queue); return; } // std::cerr << "total_merged_rows: " << total_merged_rows << ", merged_rows: " << merged_rows << "\n"; // std::cerr << "Inserting row\n"; for (size_t i = 0; i < num_columns; ++i) merged_columns[i]->insertFrom(*current->all_columns[i], current->pos); if (out_row_sources) { /// Actually, current.impl->order stores source number (i.e. cursors[current.impl->order] == current.impl) out_row_sources->emplace_back(current.impl->order); } if (!current->isLast()) { // std::cerr << "moving to next row\n"; current->next(); if (queue.empty() || !(current.greater(queue.top()))) { if (count_row_and_check_limit()) { // std::cerr << "pushing back to queue\n"; queue.push(current); return; } /// Не кладём курсор обратно в очередь, а продолжаем работать с текущим курсором. // std::cerr << "current is still on top, using current row\n"; continue; } else { // std::cerr << "next row is not least, pushing back to queue\n"; queue.push(current); } } else { /// Достаём из соответствующего источника следующий блок, если есть. // std::cerr << "It was last row, fetching next block\n"; fetchNextBlock(current, queue); } break; } if (count_row_and_check_limit()) return; } cancel(); finished = true; }
void MergingSortedBlockInputStream::initQueue(std::priority_queue<TSortCursor> & queue) { for (size_t i = 0; i < cursors.size(); ++i) if (!cursors[i].empty()) queue.push(TSortCursor(&cursors[i])); }
void AggregatingSortedBlockInputStream::merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue) { size_t merged_rows = 0; /// Вынимаем строки в нужном порядке и кладём в merged_block, пока строк не больше max_block_size while (!queue.empty()) { TSortCursor current = queue.top(); setPrimaryKeyRef(next_key, current); bool key_differs; if (current_key.empty()) /// Первый встретившийся ключ. { current_key.columns.resize(description.size()); setPrimaryKeyRef(current_key, current); key_differs = true; } else key_differs = next_key != current_key; /// если накопилось достаточно строк и последняя посчитана полностью if (key_differs && merged_rows >= max_block_size) return; queue.pop(); if (key_differs) { current_key.swap(next_key); /// Запишем данные для очередной группы. Копируем значения обычных столбцов. for (size_t i = 0, size = column_numbers_not_to_aggregate.size(); i < size; ++i) { size_t j = column_numbers_not_to_aggregate[i]; merged_columns[j]->insertFrom(*current->all_columns[j], current->pos); } /// Добавляем в агрегатные столбцы пустое состояние агрегации. Состояние будет обновлено в функции addRow. for (auto & column_to_aggregate : columns_to_aggregate) column_to_aggregate->insertDefault(); ++merged_rows; } addRow(current); if (!current->isLast()) { current->next(); queue.push(current); } else { /// Достаём из соответствующего источника следующий блок, если есть. fetchNextBlock(current, queue); } } finished = true; }
Cell top() const { return _pq.top().vertex; }
void pintar_vertices(Grafo& g, std::priority_queue<Vertice, std::vector<Vertice>, std::greater<Vertice> >& vertices) { //std::priority_queue<Vertice> vertices) { init_time(); int vistos = 0; int cant_vertices = g.cant_vertices(); // Creo vector para obtener el maximo for (int i = 0 ; i < cant_vertices ; ++i) { vertices.push(g.dame_vertice(i)); } // Recorro todos los vertices del grafo while (vistos < cant_vertices) { //std::cout << "vistos: " << vistos << " cant_vertices " << cant_vertices << std::endl; // Hallar el vertice de mayor grado Vertice vertice = vertices.top(); // std::cout << "vertice: " << vertice.dame_nombre() << std::endl; vertices.pop(); std::set<int> colores_vertice = vertice.dame_colores_posibles(); // Creo un diccionario para ver cual es el color // que mas usan los vecinos // y otro para ver cual es el que mas se repite entre los // colores posibles de los vecinos std::map<int, int> colores_usados; std::map<int, int> colores_posibles; for (int color : colores_vertice) { colores_usados.insert(std::pair<int, int> (color, 0)); colores_posibles.insert(std::pair<int, int> (color, 0)); } // recorro los vecinos del maximo std::set<int> vecinos = g.dame_vecinos(vertice.dame_nombre()); for (int v : vecinos) { int color_vecino = g.dame_color(v); if (color_vecino != -1) { // Ya esta pintado el vecino y no puedo usar ese color // Me fijo si el vertice sobre el cual estoy parado tiene a ese // color como disponible y de ser así lo aumento en el diccionario de colores std::set<int>::iterator it = colores_vertice.find(color_vecino); if (it != colores_vertice.end()) colores_usados[color_vecino]++; } else { // Si no esta pintado el vecino std::set<int> colores_vecino = g.dame_colores_posibles(v); // Por cada color que entre en conflicto sumo 1 en el diccionario for (int color : colores_vecino) { std::set<int>::iterator it = colores_vertice.find(color); if (it != colores_vertice.end()) { colores_posibles[color]++; } } } } // Tengo dos diccionarios que determinan para cada color que tiene el vértice // la cantidad de vecinos que tienen ese color pintado // y la cantidad de vecinos que tienen ese color como posibilidad // Recorro el diccionario de colores usados por mis vecinos for (int i = 0 ; i < colores_usados.size() ; ++i) { if (colores_vertice.size() > 1) { // Elijo el color que es el mas utilizado por mis vecinos int color_con_mas_apariciones = dame_el_de_maxima_aparicion(colores_usados); // Lo borro if (color_con_mas_apariciones != -1 ) colores_vertice.erase(color_con_mas_apariciones); } } // O salgo del for anterior con muchos colores disponibles porque mis vecinos no // estaban pintados // o tengo un único color disponible para pintarme int color; if (colores_vertice.size() == 1) { // Si me queda un único color en mi conjunto es el que menos conflictos me causaba // por ende pinto al grafo de esa manera std::set<int>::iterator it = colores_vertice.begin(); color = *it; } else { // Si me queda más de un color disponible busco en los posibles colores // de mis vecinos el que quizas me trae menos conflictos int min = 999; for (std::pair<const int, int>& par : colores_posibles) { if (par.second < min) { std::set<int>::iterator it = colores_vertice.find(par.first); if (it != colores_vertice.end()) { min = par.second; color = par.first; } } } } g.pintar(vertice.dame_nombre(), color); //g.imprimir(); vistos++; } acum += get_time(); }
bool empty() const { return _pq.empty(); }
int main() { scanf("%d %d", &n, &m); for (int i = 0; i < m; i++) { scanf("%d %d %d", &a, &b, &t); adj[a].push_back(std::make_pair(b, t)); adj[b].push_back(std::make_pair(a, t)); } dist[0] = 0; q.push(std::make_pair(0, 0)); for (int i = 1; i < n; i++) { dist[i] = 0x3f3f3f3f; q.push(std::make_pair(-dist[i], i)); } while (!q.empty()) { std::tie(cur_dist, cur_index) = q.top(); q.pop(); cur_dist *= -1; vis[cur_index] = 1; for (std::pair<int, int> p : adj[cur_index]) { if (!vis[p.first]) { const int alt = cur_dist + p.second; if (alt < dist[p.first]) { dist[p.first] = alt; q.push(std::make_pair(-alt, p.first)); } } } } dist2[0] = 0; q.push(std::make_pair(0, n - 1)); for (int i = 0; i < n - 1; i++) { dist2[i] = 0x3f3f3f3f; q.push(std::make_pair(-dist2[i], i)); } while (!q.empty()) { std::tie(cur_dist, cur_index) = q.top(); q.pop(); cur_dist *= -1; vis2[cur_index] = 1; for (std::pair<int, int> p : adj[cur_index]) { if (!vis2[p.first]) { const int alt = cur_dist + p.second; if (alt < dist2[p.first]) { dist2[p.first] = alt; q.push(std::make_pair(-alt, p.first)); } } } } for (int i = 0; i < n; i++) { ans = std::max(ans, dist[i] + dist2[i]); } printf("%d\n", ans); }
void push(Cell const& vertex, Value const& value) { _pq.push(Entry(vertex, value, ++_count)); }
inline size_t size(void) const { return data.size(); }
void BiDirDijkstra::explore(int cur_node, double cur_cost, int dir, std::priority_queue<PDI, std::vector<PDI>, std::greater<PDI> > &que) { int i; // Number of connected edges int con_edge = m_vecNodeVector[cur_node]->Connected_Edges_Index.size(); double edge_cost; for(i = 0; i < con_edge; i++) { int edge_index = m_vecNodeVector[cur_node]->Connected_Edges_Index[i]; // Get the edge from the edge list. GraphEdgeInfo edge = m_vecEdgeVector[edge_index]; // Get the connected node int new_node = m_vecNodeVector[cur_node]->Connected_Nodes[i]; if(cur_node == edge.StartNode) { // Current node is the startnode of the edge. For forward search it should use forward cost, otherwise it should use the reverse cost, // i.e. if the reverse direction is valid then this node may be visited from the end node. if(dir > 0) edge_cost = edge.Cost; else edge_cost = edge.ReverseCost; // Check if the direction is valid for exploration if(edge.Direction == 0 || edge_cost >= 0.0) { // Check if the current edge gives better result if(cur_cost + edge_cost < getcost(new_node, dir)) { // explore the node, and push it in the queue setcost(new_node, dir, cur_cost + edge_cost); setparent(new_node, dir, cur_node, edge.EdgeID); que.push(std::make_pair(cur_cost + edge_cost, new_node)); // Update the minimum cost found so far. if(getcost(new_node, dir) + getcost(new_node, dir * -1) < m_MinCost) { m_MinCost = getcost(new_node, dir) + getcost(new_node, dir * -1); m_MidNode = new_node; } } } } else { // Current node is the endnode of the edge. For forward search it should use reverse cost, otherwise it should use the forward cost, // i.e. if the forward direction is valid then this node may be visited from the start node. if(dir > 0) edge_cost = edge.ReverseCost; else edge_cost = edge.Cost; // Check if the direction is valid for exploration if(edge.Direction == 0 || edge_cost >= 0.0) { // Check if the current edge gives better result if(cur_cost + edge_cost < getcost(new_node, dir)) { setcost(new_node, dir, cur_cost + edge_cost); setparent(new_node, dir, cur_node, edge.EdgeID); que.push(std::make_pair(cur_cost + edge_cost, new_node)); // Update the minimum cost found so far. if(getcost(new_node, dir) + getcost(new_node, dir * -1) < m_MinCost) { m_MinCost = getcost(new_node, dir) + getcost(new_node, dir * -1); m_MidNode = new_node; } } } } } }
void HClustNNbasedSingle::computeMerge( std::priority_queue< HeapHierarchicalItem > & pq, HClustResult& res) { MESSAGE_2("[%010.3f] merging clusters\n", clock()/(float)CLOCKS_PER_SEC); volatile bool go=true; volatile size_t i = 0; #ifdef _OPENMP #pragma omp parallel #endif while (go) { #ifdef _OPENMP omp_set_lock(&pqwritelock); #endif STOPIFNOT(!pq.empty()) HeapHierarchicalItem hhi = pq.top(); if (hhi.index2 == SIZE_MAX) { pq.pop(); #ifdef _OPENMP omp_unset_lock(&pqwritelock); #endif getNearestNeighbors(pq, hhi.index1); continue; } size_t s1 = ds.find_set(hhi.index1); size_t s2 = ds.find_set(hhi.index2); if (s1 == s2) { pq.pop(); #ifdef _OPENMP omp_unset_lock(&pqwritelock); #endif continue; } #ifdef _OPENMP omp_unset_lock(&pqwritelock); //different threads will be unable to put data into pq without it #pragma omp barrier #pragma omp single #endif { hhi = pq.top(); //it can change, because other threads can push something pq.pop(); s1 = ds.find_set(hhi.index1); s2 = ds.find_set(hhi.index2); STOPIFNOT(s1 != s2); STOPIFNOT(s2 != SIZE_MAX); STOPIFNOT(hhi.index1 < hhi.index2); res.link(indices[hhi.index1], indices[hhi.index2], hhi.dist); ds.link(s1, s2); ++i; if (i == n-1) go = false;/* avoids computing unnecessary nn */ } // #pragma omp single if (MASTER_OR_SINGLE_THREAD) { if (i % 512 == 0) MESSAGE_7("\r merge clusters: %d / %d", i+1, n-1); Rcpp::checkUserInterrupt(); // may throw an exception, fast op, not thread safe } } MESSAGE_7("\r merge clusters: %d / %d \n", n-1, n-1); Rcpp::checkUserInterrupt(); }
void Push(T e) { data.push(e); }
inline void put(T item, Number priority) { elements.emplace(priority, item); }
T Pop() { auto v = data.top(); data.pop(); return v; }
bool empty() const { return open.empty(); }
bool Empty() { return data.empty(); }
namespace DeviceTime { //////////////////////////////////////////////////////////////////////////////// /// Queue of Virtual Devices static std::priority_queue<double, std::vector<double>, std::greater<double> > QUEUE; //////////////////////////////////////////////////////////////////////////////// /// Mutex Lock static std::mutex MUTEX; static std::condition_variable CONDVAR; //////////////////////////////////////////////////////////////////////////////// /// Wait for correct time to elapse if REALTIME is true static bool REALTIME = false; //////////////////////////////////////////////////////////////////////////////// /// TO_READ can be used to step through and pause events static std::atomic<uint64_t> EVENTS_TO_QUEUE( std::numeric_limits<uint64_t>::max()); //////////////////////////////////////////////////////////////////////////////// inline bool IsPaused() { return EVENTS_TO_QUEUE == 0; } //////////////////////////////////////////////////////////////////////////////// void ResetTime() { std::lock_guard<std::mutex> lock(MUTEX); // clear queue QUEUE = std::priority_queue< double, std::vector<double>, std::greater<double> >(); } //////////////////////////////////////////////////////////////////////////////// double NextTime() { //std::lock_guard<std::mutex> lock(MUTEX); if( QUEUE.empty() ) { return 0; } else { return QUEUE.top(); } } //////////////////////////////////////////////////////////////////////////////// void WaitForTime(double nextTime) { // check if timestamp is the top of the queue // if not, wait until the older timestamp is popped by another thread. std::unique_lock<std::mutex> lock(MUTEX); CONDVAR.wait( lock, [=]{return NextTime() >= nextTime;}); // TODO: Sleep for appropriate amount of time. if(REALTIME) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } //////////////////////////////////////////////////////////////////////////////// void PushTime( double T ) { // don't push in bad times // (0 is a special time when no timestamps are in use) if( T >= 0 ) { std::lock_guard<std::mutex> lock(MUTEX); QUEUE.push( T ); } } //////////////////////////////////////////////////////////////////////////////// void PopAndPushTime( double T ) { std::unique_lock<std::mutex> lock(MUTEX); // Hold up the device at the top of the queue whilst time is 'paused' while(IsPaused()) { CONDVAR.wait( lock ); } // pop top of queue which is what got us the lock in the first place! QUEUE.pop(); // don't push in bad times // (0 is a special time when no timestamps are in use) if( T >= 0 ) { QUEUE.push( T ); } // Signify that event has been queued EVENTS_TO_QUEUE--; // notify waiting threads that a change in the QUEUE has occured CONDVAR.notify_all(); } //////////////////////////////////////////////////////////////////////////////// void PopTime() { std::lock_guard<std::mutex> lock(MUTEX); QUEUE.pop(); // notify waiting threads that a change in the QUEUE has occured CONDVAR.notify_all(); } //////////////////////////////////////////////////////////////////////////////// void SetRealtime(bool realtime) { REALTIME = realtime; } //////////////////////////////////////////////////////////////////////////////// void PauseTime() { std::lock_guard<std::mutex> lock(MUTEX); EVENTS_TO_QUEUE = 0; } //////////////////////////////////////////////////////////////////////////////// void UnpauseTime() { std::lock_guard<std::mutex> lock(MUTEX); EVENTS_TO_QUEUE = std::numeric_limits<uint64_t>::max(); // notify waiting threads that a change in the QUEUE has occured CONDVAR.notify_all(); } //////////////////////////////////////////////////////////////////////////////// void TogglePauseTime() { std::lock_guard<std::mutex> lock(MUTEX); if(IsPaused()) { // unpause EVENTS_TO_QUEUE = std::numeric_limits<uint64_t>::max(); CONDVAR.notify_all(); }else{ // pause EVENTS_TO_QUEUE = 0; } } //////////////////////////////////////////////////////////////////////////////// void StepTime(int numEvents) { std::lock_guard<std::mutex> lock(MUTEX); EVENTS_TO_QUEUE = numEvents; CONDVAR.notify_all(); } }
void BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>:: BreadthFirstDualTreeTraverser<RuleType>::Traverse( BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>& queryNode, std::priority_queue<QueueFrameType>& referenceQueue) { // Store queues for the children. We will recurse into the children once our // queue is empty. std::priority_queue<QueueFrameType> leftChildQueue; std::priority_queue<QueueFrameType> rightChildQueue; while (!referenceQueue.empty()) { QueueFrameType currentFrame = referenceQueue.top(); referenceQueue.pop(); BinarySpaceTree& queryNode = *currentFrame.queryNode; BinarySpaceTree& referenceNode = *currentFrame.referenceNode; typename RuleType::TraversalInfoType ti = currentFrame.traversalInfo; rule.TraversalInfo() = ti; const size_t queryDepth = currentFrame.queryDepth; double score = rule.Score(queryNode, referenceNode); ++numScores; if (score == DBL_MAX) { ++numPrunes; continue; } // If both are leaves, we must evaluate the base case. if (queryNode.IsLeaf() && referenceNode.IsLeaf()) { // Loop through each of the points in each node. const size_t queryEnd = queryNode.Begin() + queryNode.Count(); const size_t refEnd = referenceNode.Begin() + referenceNode.Count(); for (size_t query = queryNode.Begin(); query < queryEnd; ++query) { // See if we need to investigate this point (this function should be // implemented for the single-tree recursion too). Restore the // traversal information first. // const double childScore = rule.Score(query, referenceNode); // if (childScore == DBL_MAX) // continue; // We can't improve this particular point. for (size_t ref = referenceNode.Begin(); ref < refEnd; ++ref) rule.BaseCase(query, ref); numBaseCases += referenceNode.Count(); } } else if ((!queryNode.IsLeaf()) && referenceNode.IsLeaf()) { // We have to recurse down the query node. QueueFrameType fl = { queryNode.Left(), &referenceNode, queryDepth + 1, score, rule.TraversalInfo() }; leftChildQueue.push(fl); QueueFrameType fr = { queryNode.Right(), &referenceNode, queryDepth + 1, score, ti }; rightChildQueue.push(fr); } else if (queryNode.IsLeaf() && (!referenceNode.IsLeaf())) { // We have to recurse down the reference node. In this case the recursion // order does matter. Before recursing, though, we have to set the // traversal information correctly. QueueFrameType fl = { &queryNode, referenceNode.Left(), queryDepth, score, rule.TraversalInfo() }; referenceQueue.push(fl); QueueFrameType fr = { &queryNode, referenceNode.Right(), queryDepth, score, ti }; referenceQueue.push(fr); } else { // We have to recurse down both query and reference nodes. Because the // query descent order does not matter, we will go to the left query child // first. Before recursing, we have to set the traversal information // correctly. QueueFrameType fll = { queryNode.Left(), referenceNode.Left(), queryDepth + 1, score, rule.TraversalInfo() }; leftChildQueue.push(fll); QueueFrameType flr = { queryNode.Left(), referenceNode.Right(), queryDepth + 1, score, rule.TraversalInfo() }; leftChildQueue.push(flr); QueueFrameType frl = { queryNode.Right(), referenceNode.Left(), queryDepth + 1, score, rule.TraversalInfo() }; rightChildQueue.push(frl); QueueFrameType frr = { queryNode.Right(), referenceNode.Right(), queryDepth + 1, score, rule.TraversalInfo() }; rightChildQueue.push(frr); } } // Now, recurse into the left and right children queues. The order doesn't // matter. if (leftChildQueue.size() > 0) Traverse(*queryNode.Left(), leftChildQueue); if (rightChildQueue.size() > 0) Traverse(*queryNode.Right(), rightChildQueue); }