/* 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; } } }
/* 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); }