const Node& Loader::parseTree() { auto it = fileContents.begin() + sizeof(Identifier); if (static_cast<uint8_t>(*it) != Node::START) { throw InvalidOTBFormat{}; } root.type = *(++it); root.propsBegin = ++it; NodeStack parseStack; parseStack.push(&root); for (; it != fileContents.end(); ++it) { switch(static_cast<uint8_t>(*it)) { case Node::START: { auto& currentNode = getCurrentNode(parseStack); if (currentNode.children.empty()) { currentNode.propsEnd = it; } currentNode.children.emplace_back(); auto& child = currentNode.children.back(); if (++it == fileContents.end()) { throw InvalidOTBFormat{}; } child.type = *it; child.propsBegin = it + sizeof(Node::type); parseStack.push(&child); break; } case Node::END: { auto& currentNode = getCurrentNode(parseStack); if (currentNode.children.empty()) { currentNode.propsEnd = it; } parseStack.pop(); break; } case Node::ESCAPE: { if (++it == fileContents.end()) { throw InvalidOTBFormat{}; } break; } default: { break; } } } if (!parseStack.empty()) { throw InvalidOTBFormat{}; } return root; }
/* * Prepare |pn| to be mutated in place into a new kind of node. Recycle all * |pn|'s recyclable children (but not |pn| itself!), and disconnect it from * metadata structures (the function box tree). */ void ParseNodeAllocator::prepareNodeForMutation(ParseNode *pn) { if (!pn->isArity(PN_NULLARY)) { /* Put |pn|'s children (but not |pn| itself) on a work stack. */ NodeStack stack; PushNodeChildren(pn, &stack); /* * For each node on the work stack, push its children on the work stack, * and free the node if we can. */ while (!stack.empty()) { pn = stack.pop(); if (PushNodeChildren(pn, &stack)) freeNode(pn); } } }
/* * Return the nodes in the subtree |pn| to the parser's free node list, for * reallocation. */ ParseNode * ParseNodeAllocator::freeTree(ParseNode *pn) { if (!pn) return nullptr; ParseNode *savedNext = pn->pn_next; NodeStack stack; for (;;) { if (PushNodeChildren(pn, &stack)) freeNode(pn); if (stack.empty()) break; pn = stack.pop(); } return savedNext; }
/* * Prepare |pn| to be mutated in place into a new kind of node. Recycle all * |pn|'s recyclable children (but not |pn| itself!), and disconnect it from * metadata structures (the function box tree). */ void ParseNodeAllocator::prepareNodeForMutation(ParseNode* pn) { // Nothing to do for nullary nodes. if (pn->isArity(PN_NULLARY)) return; // Put |pn|'s children (but not |pn| itself) on a work stack. NodeStack stack; PushNodeChildren(pn, &stack); // For each node on the work stack, push its children on the work stack, // and free the node if we can. while (!stack.empty()) { pn = stack.pop(); if (PushNodeChildren(pn, &stack) == PushResult::Recyclable) freeNode(pn); } }
bool Graph::findPath(int startPosition, NodeStack & s) //finds path between node teleported to and the outside world //recurses through graph, keeping track of nodes that were visted //and direction that the adventurer traveled in. Nodes already visited //or paths resulting in not being able to get out of the maze can //simply be popped off the stack. { Node * start = getNode(startPosition); if(start -> getVisited()) { return false; } start -> setVisited(true); s.push(start); if(start -> getId() == 0) { return true; } if(s.empty()) { return false; } Node ** paths = start -> getPaths(); for(int i = 0; i < 4; i ++) { if(paths[i] != 0) { start -> setDirection(i); if(findPath(paths[i] -> getId(), s)) { return true; } } } s.pop(); return false; }
Node PicklerPrivate::fromCaseOperator(Kind k, uint32_t nchildren) { kind::MetaKind m = metaKindOf(k); bool parameterized = (m == kind::metakind::PARAMETERIZED); uint32_t npops = nchildren + (parameterized? 1 : 0); NodeStack aux; while(npops > 0) { Assert(!d_stack.empty()); Node top = d_stack.top(); aux.push(top); d_stack.pop(); --npops; } NodeBuilder<> nb(d_nm, k); while(!aux.empty()) { Node top = aux.top(); nb << top; aux.pop(); } return nb; }
/* * Prepare |pn| to be mutated in place into a new kind of node. Recycle all * |pn|'s recyclable children (but not |pn| itself!), and disconnect it from * metadata structures (the function box tree). */ void ParseNodeAllocator::prepareNodeForMutation(ParseNode *pn) { if (!pn->isArity(PN_NULLARY)) { if (pn->isArity(PN_FUNC)) { /* * Since this node could be turned into anything, we can't * ensure it won't be subsequently recycled, so we must * disconnect it from the funbox tree entirely. * * Note that pn_funbox may legitimately be NULL. functionDef * applies MakeDefIntoUse to definition nodes, which can come * from prior iterations of the big loop in compileScript. In * such cases, the defn nodes have been visited by the recycler * (but not actually recycled!), and their funbox pointers * cleared. But it's fine to mutate them into uses of some new * definition. */ if (pn->pn_funbox) pn->pn_funbox->node = NULL; } /* Put |pn|'s children (but not |pn| itself) on a work stack. */ NodeStack stack; PushNodeChildren(pn, &stack); /* * For each node on the work stack, push its children on the work stack, * and free the node if we can. */ while (!stack.empty()) { pn = stack.pop(); if (PushNodeChildren(pn, &stack)) freeNode(pn); } } }
void Network::topologicalSortExecutionNetwork() { // Note: we don't need to do a full-fledged topological sort here, as we do not // have any DAG, we actually have a dependency tree. This way we can just do a // depth-first search, with ref-counting to account for diamond shapes in the tree. // this is similar to the wavefront design pattern used in parallelization // Using DFS here also has the advantage that it makes as much as possible use // of cache locality // 1- get all the nodes and count the number of refs they have NodeVector nodes = depthFirstSearch(_executionNetworkRoot); map<NetworkNode*, int> refs; // this initialization should be useless, but let's do it anyway for clarity for (int i=0; i<(int)nodes.size(); i++) refs[nodes[i]] = 0; // count the number of refs for each node for (int i=0; i<(int)nodes.size(); i++) { const NodeVector& children = nodes[i]->children(); for (int j=0; j<(int)children.size(); j++) { refs[children[j]] += 1; } } // 2- do DFS again, manually this time and only visit node which have no refs anymore _toposortedNetwork.clear(); NodeStack toVisit; toVisit.push(_executionNetworkRoot); refs[_executionNetworkRoot] = 1; while (!toVisit.empty()) { NetworkNode* currentNode = toVisit.top(); toVisit.pop(); if (--refs[currentNode] == 0) { _toposortedNetwork.push_back(currentNode->algorithm()); // keep this node, it is good const NodeVector& children = currentNode->children(); for (int i=0; i<(int)children.size(); i++) { toVisit.push(children[i]); } } } E_DEBUG(ENetwork, "-------------------------------------------------------------------------------------------"); for (int i=0; i<(int)_toposortedNetwork.size(); i++) { E_DEBUG_NONL(ENetwork, " → " << _toposortedNetwork[i]->name()); } E_DEBUG(ENetwork, ""); // for adding a newline E_DEBUG(ENetwork, "-------------------------------------------------------------------------------------------"); }
// Pre-order traversal void Node::printNoRecursion() { NodeStack* stack = new NodeStack(); stack->push(this); while( !stack->isEmpty() ) { Node* node = stack->pop(); cout << node->value() << " "; if ( node->right() ) stack->push(node->right()); if ( node->left() ) stack->push(node->left()); } delete stack; }
void OracleBuilder::exploreNode(ConcurrentMap<string, HashTable *> &tables, NodeStack &nodes, Color playFor, int commId) { Position pos; Comm::UCICommunicatorPool &pool = Comm::UCICommunicatorPool::getInstance(); Options &opt = Options::getInstance(); HashTable *oracle = tables[""]; pool.sendOption(commId, "MultiPV", to_string(opt.getMaxMoves())); //Main loop Node *current = nullptr; while ((current = nodes.poptop())) { string iterationOutput; const string currentPos = current->getPos(); Line bestLine; /*Set the chessboard to current pos*/ pos.set(currentPos); Color active = pos.side_to_move(); string signature = pos.signature(); uint64_t curHash = pos.hash(); bool insertCopyInSignTable = false; /*Lookup in signature tables*/ if (signature.length() <= opt.getMaxPiecesEnding()) { HashTable *table = nullptr; if (tables.count(signature) == 0) { string filename = opt.getTableFolder() + "/" + signature + ".autosave." + opt.getVariantAsString() + to_string(opt.getCutoffThreshold()) + ".bin"; table = new HashTable(filename); if (tables.findOrInsert(signature, table) != table) { delete table; table = tables[signature]; } } else { table = tables[signature]; } Node *s = nullptr; if ((s = table->findVal(curHash))) { current->updateStatus((Node::StatusFlag) (s->getStatus() | Node::SIGNATURE_TABLE)); if (current->getStatus() & Node::THEM) { OracleBuilder::displayNodeHistory(current); Out::output("Iteration output for error :\n" + iterationOutput); Err::handle("A node has gone from draw to mate, this is an error" " until we decide on what to do, and if it's a bug" " in the engine."); } if (oracle->findOrInsert(curHash, current) != current) delete current; continue; } else { insertCopyInSignTable = true; } } /*Try to find the position and insert it if not found*/ if (oracle->findOrInsert(curHash, current) != current) { Out::output(iterationOutput, "Position already in table.\n", 1); delete current; continue; } /* TODO rethink this, as we should probably remove the position if cut *if (OracleBuilder::cutNode(pos, current)) { * Out::output("Node cut by user-defined function", 1); * continue; *} */ Out::output(iterationOutput, "[" + color_to_string(active) + "] Proceed size : " + to_string(nodes.size()) + "\n"); /*Clear cut*/ if (!pos.hasSufficientMaterial()) { current->updateStatus(Node::DRAW); Out::output(iterationOutput, "[" + color_to_string(active) + "] Insuficient material.\n", 2); //Proceed to next node... continue; } Out::output(iterationOutput, pos.pretty(), 2); /*Hit statistic*/ __atomic_fetch_add(&OracleFinder::signStat_[signature], 1, __ATOMIC_SEQ_CST); string position = "position fen "; position += pos.fen(); pool.send(commId, position); if (playFor != active) { /*We are on a node where the opponent has to play*/ current->updateStatus(Node::AGAINST); /*proceedAgainstNode(pos, current);*/ vector<Move> all = gen_all(pos); /* * Push all node for the side we "play for". * eg: if we are building an oracle for white, we need to push all * possible white positions when computing a black node. */ Out::output(iterationOutput, "Push all lines : ", 2); for (Move m : all) { string uciMv = move_to_string(m); Out::output(iterationOutput, "+", 2); if (!pos.tryAndApplyMove(m)) Err::handle("Illegal move pushed ! (While proceeding against Node)"); string fen = pos.fen(); pos.undoLastMove(); Node *next = new Node(current, fen, Node::PENDING); nodes.push(next); MoveNode move(uciMv, next); current->safeAddMove(move); } Out::output(iterationOutput, "\n", 2); continue; } /**********************************************/ /*Here we are on a node with "playfor" to play*/ /**********************************************/ const vector<Line> &lines = pool.getResultLines(commId); /*Thinking according to the side the engine play for*/ int moveTime = opt.getPlayforMovetime(); Out::output(iterationOutput, "[" + color_to_string(active) + "] Thinking... (" + to_string(moveTime) + ")\n", 1); string cmd = "go "; switch (opt.getSearchMode()) { case DEPTH: cmd += "depth " + to_string(opt.getSearchDepth()); break; case MIXED://Intentional no-break /*TODO: implement mixed search ? likely not, * early multipv in stockfish*/ case TIME: default: cmd += "movetime " + to_string(moveTime); break; } //Send go and wait for engine to finish thinking pool.sendAndWaitBestmove(commId, cmd); Out::output(iterationOutput, Utils::getPrettyLines(pos, lines), 2); bestLine = lines[0]; bool skipThisNode = false; if (bestLine.empty()) { //STALEMATE current->updateStatus(Node::STALEMATE); Out::output(iterationOutput, "[" + color_to_string(active) + "] Bestline is stalemate (cut)\n", 2); //Proceed to next node... skipThisNode = true; } else if (bestLine.isMat()) { Out::output(iterationOutput, "[" + color_to_string(active) + "] Bestline is mate (cut)\n", 2); /*Eval is always negative if it's bad for us*/ if (bestLine.getEval() < 0) { current->updateStatus((Node::StatusFlag)(Node::MATE | Node::THEM)); Out::output("Iteration output for error :\n" + iterationOutput); OracleBuilder::displayNodeHistory(current); Err::handle("A node has gone from draw to mate, this is an error" " until we decide on what to do, and if it's a bug" " in the engine."); } else { current->updateStatus((Node::StatusFlag)(Node::MATE | Node::US)); } skipThisNode = true; } else if (fabs(bestLine.getEval()) > opt.getCutoffThreshold()) { Out::output(iterationOutput, "[" + color_to_string(active) + "] Bestline is above threshold (cut)\n", 2); if (bestLine.getEval() < 0) { current->updateStatus((Node::StatusFlag)(Node::THRESHOLD | Node::THEM)); Out::output("Iteration output for error :\n" + iterationOutput); OracleBuilder::displayNodeHistory(current); Err::handle("A node has gone from draw to threshold, this is an error" " until we decide on what to do, and if it's a bug" " in the engine."); } else { current->updateStatus((Node::StatusFlag)(Node::THRESHOLD | Node::US)); } skipThisNode = true; } /*Trick to avoid code duplicaton for inserting copy in table*/ if (!skipThisNode) { current->updateStatus(Node::DRAW); /* If we are not in fullBuild mode, just insert a pending node in * table if the signature is low enough */ if (!opt.fullBuild() && signature.length() <= opt.getMaxPiecesEnding()) { if (oracle->findOrInsert(curHash, current) != current) delete current; else current->updateStatus((Node::StatusFlag) (current->getStatus() | Node::PENDING)); continue; } } if (insertCopyInSignTable) { Node *cpy = current->lightCopy(); if (tables[signature]->findOrInsert(curHash, cpy) != cpy) delete cpy; } if (skipThisNode) continue; /*If we are here, bestLine is "draw", and we should continue to explore*/ vector<Line> playableLines; /*Select all the candidate lines (bestmove +- deviation)*/ for (Line l : lines) { if (!(l.empty() || l.isMat()) && (fabs(bestLine.getEval() - l.getEval()) <= opt.getBestmoveDeviation() || l.getEval() >= -1)) playableLines.push_back(l); } /* *Then proceed the balanced lines according to the side the engine *play for. */ if (playFor != active) Err::handle("Current side should be the engine plays for"); /* * General Idea : try to force repetition by trying to find a playable * position in the hashtable. If not sort the playable moves * according to a user defined comparator */ Node *next = NULL; /*The elected move*/ string mv; /*Try to find a position in the table*/ /* There must be a reason to go trough it backward, but I can't * remember it right now. */ Line l; for (auto rit = playableLines.rbegin(); rit != playableLines.rend(); ++rit) { l = *rit; mv = l.firstMove(); if (!pos.tryAndApplyMove(mv)) { Err::output(pos.pretty()); Err::output("Move : " + mv); Err::handle("Illegal move while proceeding a draw node"); } /*This is the next pos*/ uint64_t hashpos = pos.hash(); pos.undoLastMove(); //Jean Louis' idea to force finding positions in oracle next = oracle->findVal(hashpos); if (next) { next->safeAddParent(current); break; } } /*No repetition found, sort the playable lines*/ if (!next) { std::sort(playableLines.begin(), playableLines.end(), [&pos](const Line &lhs, const Line &rhs) { return pos.compareLines(lhs, rhs); }); l = playableLines[0]; mv = l.firstMove(); pos.tryAndApplyMove(mv); string fenpos = pos.fen(); pos.undoLastMove(); //no next position in the table, push the node to stack next = new Node(current, fenpos, Node::PENDING); Out::output(iterationOutput, "[" + color_to_string(active) + "] Pushed first line (" + mv + ") : " + fenpos + "\n", 2); nodes.push(next); } /*Whatever the move is, add it to our move list*/ MoveNode move(mv, next); current->safeAddMove(move); Out::output(iterationOutput, "-----------------------\n", 1); /*Send the whole iteration output*/ Out::output(iterationOutput); } }
SEXP gbm_plot( SEXP covariates, // vector or matrix of points to make predictions SEXP whichvar, // index of which var cols of X are SEXP num_trees, // number of trees to use SEXP init_func_est, // initial value SEXP fitted_trees, // tree list object SEXP categorical_splits, // categorical split list object SEXP var_types // vector of variable types ) { BEGIN_RCPP int tree_num = 0; int obs_num = 0; int class_num = 0; const Rcpp::NumericMatrix kCovarMat(covariates); const int kNumRows = kCovarMat.nrow(); const int kNumTrees = Rcpp::as<int>(num_trees); const Rcpp::IntegerVector kWhichVars(whichvar); const Rcpp::GenericVector kFittedTrees(fitted_trees); const Rcpp::GenericVector kSplits(categorical_splits); const Rcpp::IntegerVector kVarType(var_types); Rcpp::NumericVector predicted_func(kNumRows, Rcpp::as<double>(init_func_est)); if (kCovarMat.ncol() != kWhichVars.size()) { throw gbm_exception::InvalidArgument("shape mismatch"); } for (tree_num = 0; tree_num < kNumTrees; tree_num++) { const Rcpp::GenericVector kThisTree = kFittedTrees[tree_num]; const Rcpp::IntegerVector kThisSplitVar = kThisTree[0]; const Rcpp::NumericVector kThisSplitCode = kThisTree[1]; const Rcpp::IntegerVector kThisLeftNode = kThisTree[2]; const Rcpp::IntegerVector kThisRightNode = kThisTree[3]; const Rcpp::IntegerVector kThisMissingNode = kThisTree[4]; const Rcpp::NumericVector kThisWeight = kThisTree[6]; for (obs_num = 0; obs_num < kNumRows; obs_num++) { NodeStack stack; stack.push(0, 1.0); while (!stack.empty()) { const std::pair<int, double> top = stack.pop(); int iCurrentNode = top.first; const double kWeight = top.second; if (kThisSplitVar[iCurrentNode] == -1) // terminal node { predicted_func[class_num * kNumRows + obs_num] += kWeight * kThisSplitCode[iCurrentNode]; } else // non-terminal node { // is this a split variable that interests me? const Rcpp::IntegerVector::const_iterator found = std::find(kWhichVars.begin(), kWhichVars.end(), kThisSplitVar[iCurrentNode]); if (found != kWhichVars.end()) { const int kPredVar = found - kWhichVars.begin(); const double kXValue = kCovarMat(obs_num, kPredVar); // missing? if (ISNA(kXValue)) { stack.push(kThisMissingNode[iCurrentNode], kWeight); } // continuous? else if (kVarType[kThisSplitVar[iCurrentNode]] == 0) { if (kXValue < kThisSplitCode[iCurrentNode]) { stack.push(kThisLeftNode[iCurrentNode], kWeight); } else { stack.push(kThisRightNode[iCurrentNode], kWeight); } } else // categorical { const Rcpp::IntegerVector kCatSplits = kSplits[kThisSplitCode[iCurrentNode]]; const int kCatSplitIndicator = kCatSplits[kXValue]; if (kCatSplitIndicator == -1) { stack.push(kThisLeftNode[iCurrentNode], kWeight); } else if (kCatSplitIndicator == 1) { stack.push(kThisRightNode[iCurrentNode], kWeight); } else // handle unused level { stack.push(kThisMissingNode[iCurrentNode], kWeight); } } } // iPredVar != -1 else // not interested in this split, average left and right { const int kRight = kThisRightNode[iCurrentNode]; const int kLeft = kThisLeftNode[iCurrentNode]; const double kRightWeight = kThisWeight[kRight]; const double kLeftWeight = kThisWeight[kLeft]; stack.push(kRight, kWeight * kRightWeight / (kRightWeight + kLeftWeight)); stack.push(kLeft, kWeight * kLeftWeight / (kRightWeight + kLeftWeight)); } } // non-terminal node } // while(cStackNodes > 0) } // iObs } // iTree return Rcpp::wrap(predicted_func); END_RCPP } // gbm_plot