PsTreeNodeWriter.cpp

// PsTreeNodeWriter.cpp
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2010

@import "PsTreeNodeWriter.h"
#include "Ceda/cxUtils/Tracer.h"

///////////////////////////////////////////////////////////////////////////////////////////////////
// PsTreeNodeWriter

PsTreeNodeWriter::PsTreeNodeWriter(PsTreeNode* rootNode, bool seedFromClock, bool enableTrace) : 
    m_isaac(seedFromClock),
    m_rootNode(rootNode),
    m_enableTrace(enableTrace)
{
}

PsTreeNode* PsTreeNodeWriter::PickNode()
{
    ceda::xvector<PsTreeNode*> nodes;
    m_rootNode->GetAllNodes(nodes);
    ceda::ssize_t i = m_isaac.GetUniformDistInteger_ssize_t(0,nodes.size());
    cxAlwaysAssert(0 <= i && i < nodes.size());
    return nodes[i];
}

void PsTreeNodeWriter::AddRandomNode(PsTreeNode* c)
{
    PsTreeNode* p = PickNode();
    cxAlwaysAssert(p);
    ceda::ssize_t n = p->GetNumChildren();
    ceda::ssize_t i = m_isaac.GetUniformDistInteger_ssize_t(0,n+1);
    cxAlwaysAssert(0 <= i && i <= n);
    p->AddChild(i,c);
    p->ValidateChildren();
}

void PsTreeNodeWriter::DeleteRandomNode()
{
    PsTreeNode* p = PickNode();
    cxAlwaysAssert(p);
    if (p != m_rootNode)
    {
        p->DeleteThisNode();
        p->ValidateChildren();
    }
}

void PsTreeNodeWriter::MoveRandomNode()
{
    PsTreeNode* c = PickNode();
    cxAlwaysAssert(c);
    if (c != m_rootNode)
    {
        c->RemoveThisNode();
        AddRandomNode(c);
    }
}

void PsTreeNodeWriter::AddRandomAmount()
{
    PsTreeNode* p = PickNode();
    cxAlwaysAssert(p);
    p->OffsetAmount( m_isaac.GetUniformDistInteger(0,100) );
}

void PsTreeNodeWriter::Run(ceda::ssize_t minOps, ceda::ssize_t maxOps)
{
    ceda::TraceIndenter indent(2);

    m_rootNode->CheckInvariant();

    ceda::ssize_t n = m_isaac.GetUniformDistInteger_ssize_t(minOps,maxOps);
    for (ceda::ssize_t k=0 ; k < n ; ++k)
    {
        int i = m_isaac.GetUniformDistInteger(0,4);
        if (i == 0)
        {
            if (m_enableTrace)
            {
                Tracer() << "Adding node\n";
            }

            PsTreeNode* n = new PsTreeNode();
            RegisterGcObject(n);
            AddRandomNode(n);
        }
        else if (i == 1)
        {
            if (m_enableTrace)
            {
                Tracer() << "Deleting node\n";
            }
            DeleteRandomNode();
        }
        else if (i == 2)
        {
            if (m_enableTrace)
            {
                Tracer() << "Moving node\n";
            }
            MoveRandomNode();
        }
        else if (i == 3)
        {
            if (m_enableTrace)
            {
                Tracer() << "Adding amount\n";
            }
            AddRandomAmount();
        }
        else
        {
            break;
        }
    }

    //m_rootNode->CheckInvariant();
    if (m_enableTrace)
    {
        Tracer() << "Size of tree = " << m_rootNode->GetNumNodes() << '\n';
    }
}