bool SolverPNS::pns(const Board & board, PNSNode * node, int depth, uint32_t tp, uint32_t td){ iters++; if(maxdepth < depth) maxdepth = depth; if(node->children.empty()){ if(ctmem.memalloced() >= memlimit) return false; int numnodes = board.movesremain(); nodes += node->alloc(numnodes, ctmem); if(lbdist) dists.run(&board); int i = 0; for(Board::MoveIterator move = board.moveit(true); !move.done(); ++move){ int outcome, pd; if(ab){ Board next = board; next.move(*move, false, false); pd = 0; outcome = (ab == 1 ? solve1ply(next, pd) : solve2ply(next, pd)); nodes_seen += pd; }else{ outcome = board.test_win(*move); pd = 1; } if(lbdist && outcome < 0) pd = dists.get(*move); node->children[i] = PNSNode(*move).outcome(outcome, board.toplay(), ties, pd); i++; } node->children.shrink(i); //if symmetry, there may be extra moves to ignore nodes_seen += i; updatePDnum(node); return true; } bool mem; do{ PNSNode * child = node->children.begin(), * child2 = node->children.begin(), * childend = node->children.end(); uint32_t tpc, tdc; if(df){ for(PNSNode * i = node->children.begin(); i != childend; i++){ if(i->delta <= child->delta){ child2 = child; child = i; }else if(i->delta < child2->delta){ child2 = i; } } tpc = min(INF32/2, (td + child->phi - node->delta)); tdc = min(tp, (uint32_t)(child2->delta*(1.0 + epsilon) + 1)); }else{ tpc = tdc = 0; while(child->delta != node->phi) child++; } Board next = board; next.move(child->move, false, false); uint64_t itersbefore = iters; mem = pns(next, child, depth + 1, tpc, tdc); child->work += iters - itersbefore; if(child->phi == 0 || child->delta == 0) //clear child's children nodes -= child->dealloc(ctmem); if(updatePDnum(node) && !df) break; }while(!timeout && mem && (!df || (node->phi < tp && node->delta < td))); return mem; }
bool SolverPNS2::SolverThread::pns(const Board & board, PNSNode * node, int depth, uint32_t tp, uint32_t td){ iters++; if(solver->maxdepth < depth) solver->maxdepth = depth; if(node->children.empty()){ if(node->terminal()) return true; if(solver->ctmem.memalloced() >= solver->memlimit) return false; if(!node->children.lock()) return false; int numnodes = board.movesremain(); CompactTree<PNSNode>::Children temp; temp.alloc(numnodes, solver->ctmem); PLUS(solver->nodes, numnodes); if(solver->lbdist) dists.run(&board); int i = 0; for(Board::MoveIterator move = board.moveit(true); !move.done(); ++move){ int outcome, pd; if(solver->ab){ Board next = board; next.move(*move); pd = 0; outcome = (solver->ab == 1 ? solve1ply(next, pd) : solve2ply(next, pd)); PLUS(solver->nodes_seen, pd); }else{ outcome = board.test_win(*move); pd = 1; } if(solver->lbdist && outcome < 0) pd = dists.get(*move); temp[i] = PNSNode(*move).outcome(outcome, board.toplay(), solver->ties, pd); i++; } temp.shrink(i); //if symmetry, there may be extra moves to ignore node->children.swap(temp); assert(temp.unlock()); PLUS(solver->nodes_seen, i); updatePDnum(node); return true; } bool mem; do{ PNSNode * child = node->children.begin(), * child2 = node->children.begin(), * childend = node->children.end(); uint32_t tpc, tdc; if(solver->df){ for(PNSNode * i = node->children.begin(); i != childend; i++){ if(i->refdelta() <= child->refdelta()){ child2 = child; child = i; }else if(i->refdelta() < child2->refdelta()){ child2 = i; } } tpc = min(INF32/2, (td + child->phi - node->delta)); tdc = min(tp, (uint32_t)(child2->delta*(1.0 + solver->epsilon) + 1)); }else{ tpc = tdc = 0; for(PNSNode * i = node->children.begin(); i != childend; i++) if(child->refdelta() > i->refdelta()) child = i; } Board next = board; next.move(child->move); child->ref(); uint64_t itersbefore = iters; mem = pns(next, child, depth + 1, tpc, tdc); child->deref(); PLUS(child->work, iters - itersbefore); if(updatePDnum(node) && !solver->df) break; }while(!solver->timeout && mem && (!solver->df || (node->phi < tp && node->delta < td))); return mem; }