Esempio n. 1
0
void SgUctTree::SetMustplay(const SgUctNode& node,
                            const std::vector<SgUctMoveInfo>& moves,
                            bool deleteChildTrees)
{
    for (SgUctChildIterator it(*this, node); it; ++it)
    {
        SgUctNode* child = const_cast<SgUctNode*>(&(*it));
        bool found = false;
        for (size_t j = 0; j < moves.size(); ++j) 
        {
            if (child->Move() == moves[j].m_move)
            {
                found = true;
                if (moves[j].m_count > 0)
                    child->AddGameResults(moves[j].m_value, moves[j].m_count);
                if (moves[j].m_raveCount > 0)
                    child->AddRaveValue(moves[j].m_raveValue, 
                                        moves[j].m_raveCount);
                if (deleteChildTrees) 
                {
                    // Write order dependency
                    child->SetNuChildren(0);
                    SgSynchronizeThreadMemory();                    
                    child->SetFirstChild(0);
                }
                break;
            }
        }
        if (!found)
            child->SetProvenType(SG_PROVEN_WIN); // mark as loss
    }
    SgSynchronizeThreadMemory();
}
Esempio n. 2
0
/** Recursive function used by SgUctTree::ExtractSubtree and
    SgUctTree::CopyPruneLowCount.
    @param target The target tree.
    @param targetNode The target node; it is already created but the content
    not yet copied
    @param node The node in the source tree to be copied.
    @param minCount The minimum count (SgUctNode::MoveCount()) of a non-root
    node in the source tree to copy
    @param currentAllocatorId The current node allocator. Will be incremented
    in each call to CopySubtree to use node allocators of target tree evenly.
    @param warnTruncate Print warning to SgDebug() if tree was
    truncated (e.g due to reassigning nodes to different allocators)
    @param[in,out] abort Flag to abort copying. Must be initialized to false
    by top-level caller
    @param timer
    @param maxTime See ExtractSubtree() 
    @param alwaysKeepProven Copy proven nodes even if below minCount */
SgUctProvenType SgUctTree::CopySubtree(SgUctTree& target, SgUctNode& targetNode,
                                       const SgUctNode& node, SgUctValue minCount,
                                       std::size_t& currentAllocatorId,
                                       bool warnTruncate, bool& abort, SgTimer& timer,
                                       double maxTime, bool alwaysKeepProven) const

{
    SG_ASSERT(Contains(node));
    SG_ASSERT(target.Contains(targetNode));
    targetNode.CopyDataFrom(node);

    if (! node.HasChildren())
        return node.ProvenType();

    if (  node.MoveCount() < minCount
       && (! node.IsProven() || ! alwaysKeepProven)
       )
    {
        targetNode.SetProvenType(SG_NOT_PROVEN);
        return SG_NOT_PROVEN;
    }
            
    SgUctAllocator& targetAllocator = target.Allocator(currentAllocatorId);
    int nuChildren = node.NuChildren();
    if (! abort)
    {
        if (! targetAllocator.HasCapacity(nuChildren))
        {
            // This can happen even if target tree has same maximum number of
            // nodes, because allocators are used differently.
            if (warnTruncate)
                SgDebug() <<
                "SgUctTree::CopySubtree: Truncated (allocator capacity)\n";
            abort = true;
        }
        if (timer.IsTimeOut(maxTime, 10000))
        {
            if (warnTruncate)
                SgDebug() << "SgUctTree::CopySubtree: Truncated (max time)\n";
            abort = true;
        }
        if (SgUserAbort())
        {
            if (warnTruncate)
                SgDebug() << "SgUctTree::CopySubtree: Truncated (aborted)\n";
            abort = true;
        }
    }
    if (abort)
    {
        // Don't copy the children and set the pos count to zero (should
        // reflect the sum of children move counts)
        targetNode.SetPosCount(0);
        targetNode.SetProvenType(SG_NOT_PROVEN);
        return SG_NOT_PROVEN;
    }

    SgUctNode* firstTargetChild = targetAllocator.Finish();
    targetNode.SetFirstChild(firstTargetChild);
    targetNode.SetNuChildren(nuChildren);

    // Create target nodes first (must be contiguous in the target tree)
    targetAllocator.CreateN(nuChildren);

    // Recurse
    SgUctProvenType childProvenType;
    SgUctProvenType parentProvenType = SG_PROVEN_LOSS;
    SgUctNode* targetChild = firstTargetChild;
    for (SgUctChildIterator it(*this, node); it; ++it, ++targetChild)
    {
        const SgUctNode& child = *it;
        ++currentAllocatorId; // Cycle to use allocators uniformly
        if (currentAllocatorId >= target.NuAllocators())
            currentAllocatorId = 0;
        childProvenType = CopySubtree(target, *targetChild, child, 
                                      minCount, currentAllocatorId,
                                      warnTruncate, abort, timer,
                                      maxTime, alwaysKeepProven);
        if (childProvenType == SG_PROVEN_LOSS)
            parentProvenType = SG_PROVEN_WIN;
        else if (  parentProvenType != SG_PROVEN_WIN
                && childProvenType == SG_NOT_PROVEN)
            parentProvenType = SG_NOT_PROVEN;
    }
    targetNode.SetProvenType(parentProvenType);
    return parentProvenType;
}