void AgentPNS::PNSThread::run(){ while(true){ switch(agent->threadstate){ case Thread_Cancelled: //threads should exit return; case Thread_Wait_Start: //threads are waiting to start case Thread_Wait_Start_Cancelled: agent->runbarrier.wait(); CAS(agent->threadstate, Thread_Wait_Start, Thread_Running); CAS(agent->threadstate, Thread_Wait_Start_Cancelled, Thread_Cancelled); break; case Thread_Wait_End: //threads are waiting to end agent->runbarrier.wait(); CAS(agent->threadstate, Thread_Wait_End, Thread_Wait_Start); break; case Thread_Running: //threads are running if(agent->root.terminal()){ //solved CAS(agent->threadstate, Thread_Running, Thread_Wait_End); break; } if(agent->ctmem.memalloced() >= agent->memlimit){ //out of memory, start garbage collection CAS(agent->threadstate, Thread_Running, Thread_GC); break; } pns(agent->rootboard, &agent->root, 0, INF32/2, INF32/2); break; case Thread_GC: //one thread is running garbage collection, the rest are waiting case Thread_GC_End: //once done garbage collecting, go to wait_end instead of back to running if(agent->gcbarrier.wait()){ logerr("Starting solver GC with limit " + to_str(agent->gclimit) + " ... "); Time starttime; agent->garbage_collect(& agent->root); Time gctime; agent->ctmem.compact(1.0, 0.75); Time compacttime; logerr(to_str(100.0*agent->ctmem.meminuse()/agent->memlimit, 1) + " % of tree remains - " + to_str((gctime - starttime)*1000, 0) + " msec gc, " + to_str((compacttime - gctime)*1000, 0) + " msec compact\n"); if(agent->ctmem.meminuse() >= agent->memlimit/2) agent->gclimit = (unsigned int)(agent->gclimit*1.3); else if(agent->gclimit > 5) agent->gclimit = (unsigned int)(agent->gclimit*0.9); //slowly decay to a minimum of 5 CAS(agent->threadstate, Thread_GC, Thread_Running); CAS(agent->threadstate, Thread_GC_End, Thread_Wait_End); } agent->gcbarrier.wait(); break; } } }
void SolverPNS::run_pns(){ while(!timeout && root.phi != 0 && root.delta != 0){ if(!pns(rootboard, &root, 0, INF32/2, INF32/2)){ logerr("Starting solver GC with limit " + to_str(gclimit) + " ... "); Time starttime; garbage_collect(& root); Time gctime; ctmem.compact(1.0, 0.75); Time compacttime; logerr(to_str(100.0*ctmem.meminuse()/memlimit, 1) + " % of tree remains - " + to_str((gctime - starttime)*1000, 0) + " msec gc, " + to_str((compacttime - gctime)*1000, 0) + " msec compact\n"); if(ctmem.meminuse() >= memlimit/2) gclimit = (unsigned int)(gclimit*1.3); else if(gclimit > 5) gclimit = (unsigned int)(gclimit*0.9); //slowly decay to a minimum of 5 } } }
int main() { AAutoPtr<AObjectContainer> pns(new AObjectContainer("root")); try { __populate(*pns.get()); //test_iterator(); __insert(*pns.get()); //__display(*pns); } catch(AException& ex) { std::cout << ex.what() << std::endl; } catch(...) { std::cout << "Unknown exception caught!" << std::endl; } return 0; }
bool AgentPNS::PNSThread::pns(const Board & board, Node * node, int depth, uint32_t tp, uint32_t td){ iters++; if(agent->maxdepth < depth) agent->maxdepth = depth; if(node->children.empty()){ if(node->terminal()) return true; if(agent->ctmem.memalloced() >= agent->memlimit) return false; if(!node->children.lock()) return false; int numnodes = board.moves_avail(); CompactTree<Node>::Children temp; temp.alloc(numnodes, agent->ctmem); unsigned int i = 0; unsigned int seen = 0; for(MoveIterator move(board); !move.done(); ++move){ int outcome = solve1ply(move.board(), seen); unsigned int pd = 1; temp[i] = Node(*move).outcome(outcome, board.toplay(), agent->ties, pd); i++; } PLUS(agent->nodes, i); temp.shrink(i); //if symmetry, there may be extra moves to ignore node->children.swap(temp); assert(temp.unlock()); PLUS(agent->nodes_seen, seen); updatePDnum(node); return true; } bool mem; do{ Node * child = node->children.begin(), * child2 = node->children.begin(), * childend = node->children.end(); uint32_t tpc, tdc; if(agent->df){ for(Node * 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 + agent->epsilon) + 1)); }else{ tpc = tdc = 0; for(Node * 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) && !agent->df) break; }while(!agent->timeout && mem && (!agent->df || (node->phi < tp && node->delta < td))); return mem; }
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; }