Example #1
0
        /* create (if necessary) all of the nodes in the current context */
        void createNodesInCurrentContext(symbol_list_t context)
        {
            CTNode ctn = m_root;

            for (UInt64 i = 0; i < context.size(); i++)
            {
                // scan context and make up new nodes as we go along
                // and insert in tree as necessary
                int    lp      = context.ibits((int)i);
                CTNode nxt_ctn = ctn.m_child[lp];
                if (nxt_ctn == null)
                {
                    //void *p = m_ctnode_pool.malloc();
                    //assert(p != NULL);  // TODO: make more robust
                    CTNode p = new CTNode();
                    ctn.m_child[lp] = p;
                    nxt_ctn         = p;
                }
                ctn = nxt_ctn;
            }
        }
Example #2
0
/* removes the most recently observed symbol from the context tree */

        /*
         * void revert(UInt64  offset) {
         *
         * m_cts[offset].revert();
         * for (size_t i=0; i < m_cts.size(); i++) {
         * if (i != offset) m_cts[i].m_history.pop_back();
         * }
         * }*/
        // removes the most recently observed symbol from the context tree
        public void revert()
        {
            // TODONE: implement
            if (m_history.size() == 0)
            {
                return;
            }

            // 1. remove the most recent symbol from the context buffer
            symbol_t sym = m_history.back();

            m_history.pop_back();
            // compute the current context
            symbol_list_t context = new symbol_list_t(0);     //m_depth);

            // context.reserve((int)m_depth);
            getContext(context);

            // no need to undo a context tree update if there was
            // not enough context to begin with
            if (context.size() < m_depth)
            {
                return;
            }
            // 2. determine the path to the leaf nodes
            Stack path = new Stack();

            path.Push(m_root);
            // add the path to the leaf nodes
            CTNode ctn = m_root;

            for (UInt64 i = 0; i < context.size() && ctn != null; i++)
            {
                ctn = ctn.m_child[context.ibits(i)];
                path.Push(ctn);
            }

            // 3. update the probability estimates from the leaf node back up to the root,
            //    deleting any superfluous nodes as we go
            for (; path.Count != 0; path.Pop())
            {
                ctn = (CTNode)path.Peek();  //top();
                if (ctn == null)
                {
                    break;
                }
                // undo the previous KT estimate update
                ctn.m_count[sym? 1:0]--;
                double log_kt_mul = ctn.logKTMul(sym);
                ctn.m_log_prob_est -= log_kt_mul;

                // reclaim memory for any children nodes that now have seen no data
                for (UInt64 i = 0; i < 2; i++)
                {
                    // bool sym = symbols[i];
                    bool my_sym = (i == 1);
                    if (ctn.m_child[my_sym ? 1 : 0] != null && ctn.m_child[my_sym ? 1 : 0].visits() == 0)
                    {
                        //m_ctnode_pool.free(ctn.m_child[sym]);
                        ctn.m_child[my_sym ? 1 : 0] = null;
                    }
                }

                // update the weighted probabilities
                if (path.Count == (int)m_depth + 1)
                {
                    ctn.m_log_prob_weighted = ctn.logProbEstimated();
                }
                else
                {
                    // computes P_w = log{0.5 * [P_kt + P_w0*P_w1]}
                    double log_prob_on = ctn.child(true) != null?ctn.child(true).logProbWeighted() : 0.0;

                    double log_prob_off = ctn.child(false) != null?ctn.child(false).logProbWeighted() : 0.0;

                    double log_one_plus_exp = log_prob_off + log_prob_on - ctn.logProbEstimated();

                    // NOTE: no need to compute the log(1+e^x) if x is large, plus it avoids overflows
                    if (log_one_plus_exp < 100.0)
                    {
                        log_one_plus_exp = Math.Log(1.0 + Math.Exp(log_one_plus_exp));
                    }

                    ctn.m_log_prob_weighted = log_point_five + ctn.logProbEstimated() + log_one_plus_exp;
                }
            }
        }
Example #3
0
        /* updates the context tree with a single symbol */
        void update(symbol_t sym)
        {
            // TODONE: implement

            // compute the current context
            symbol_list_t context = new symbol_list_t(0); //m_depth);

            //context.reserve((int) m_depth);
            getContext(context);
            // if we have not seen enough context, append the symbol
            // to the history buffer and skip updating the context tree
            if (context.size() < m_depth)
            {
                m_history.push_back(sym);
                return;
            }
            // 1. create new nodes in the context tree (if necessary)

            createNodesInCurrentContext(context);
            // 2. walk down the tree to the relevant leaf context, saving the path as we go
            Stack path = new Stack();

            path.Push(m_root);     // add the empty context

            // add the path to the leaf nodes
            CTNode ctn = m_root;

            for (UInt64 i = 0; i < context.size(); i++)
            {
                ctn = ctn.m_child[context.ibits((int)i)];
                path.Push(ctn);
            }
            // 3. update the probability estimates from the leaf node back up to the root

            for (; path.Count != 0; path.Pop())
            {
                CTNode n = (CTNode)path.Peek();     // .Top();

                // update the KT estimate and counts
                double log_kt_mul = n.logKTMul(sym);
                n.m_log_prob_est += log_kt_mul;
                n.m_count[(sym ? 1 : 0)]++;

                // update the weighted probabilities
                if (path.Count == (int)m_depth + 1)
                {
                    n.m_log_prob_weighted = n.logProbEstimated();
                }
                else
                {
                    // computes P_w = log{0.5 * [P_kt + P_w0*P_w1]}
                    double log_prob_on = n.child(true) != null?n.child(true).logProbWeighted() : 0.0;

                    double log_prob_off = n.child(false) != null?n.child(false).logProbWeighted() : 0.0;

                    double log_one_plus_exp = log_prob_off + log_prob_on - n.logProbEstimated();

                    // NOTE: no need to compute the log(1+e^x) if x is large, plus it avoids overflows
                    if (log_one_plus_exp < 100.0)
                    {
                        log_one_plus_exp = Math.Log(1.0 + Math.Exp(log_one_plus_exp));
                    }

                    n.m_log_prob_weighted = log_point_five + n.logProbEstimated() + log_one_plus_exp;
                }
            }



            // 4. save the new symbol to the context buffer
            m_history.push_back(sym);
        }
Example #4
0
        // clear the entire context tree
        public void clear()
        {
            m_history.clear();

            m_root = new CTNode();
        }
Example #5
0
        const double log_point_five = -0.69314718055994530941723212145818; //Math.Log(0.5);

        public ContextTree(UInt64 depth)
        {
            m_root    = new CTNode();
            m_depth   = depth;
            m_history = new history_t();
        }