예제 #1
0
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;
}
예제 #2
0
/*
 * 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);
        }
    }
}
예제 #3
0
/*
 * 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;
}
예제 #4
0
/*
 * 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);
    }
}
예제 #5
0
파일: Graph.C 프로젝트: schambersnh/school
		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;
		}
예제 #6
0
파일: pickler.cpp 프로젝트: dddejan/CVC4
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;
}
예제 #7
0
/*
 * 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);
        }
    }
}
예제 #8
0
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, "-------------------------------------------------------------------------------------------");
}
예제 #9
0
// 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;
}
예제 #10
0
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);
    }
}
예제 #11
0
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