/** * dr=sum_j v_j dv_j; ddr=sum_j dv_j^2 * v_j = bar_j - bar_{p(j)} where p(j) is j's parent. * * output: newleaf_v, newleaf_dep_factor, focus_dbar, * vdv_sum, dv2_dum, dr, ddr **/ void AzReg_Tsrbase::update() { /* vdv_sum, dv2_sum: don't include new leaf nodes */ /* dr, ddr: include new leaf nodes */ dr = ddr = 0; if (forNewLeaf) { checkLeaf("update"); /*--- new leaf ---*/ newleaf_v = get_newleaf_v(); double dv = get_newleaf_dv(); int newleaf_depth = get_newleaf_depth(); newleaf_dep_factor = reg_depth->apply(1, newleaf_depth); dr += newleaf_v*dv*newleaf_dep_factor; ddr += dv*dv*newleaf_dep_factor; /*--- new leaf's sibling (v is the same) ---*/ dv = get_newleaf_sib_dv(); dr += newleaf_v*dv*newleaf_dep_factor; ddr += dv*dv*newleaf_dep_factor; focus_dbar = av_dbar.point(focus_nx)->get(focus_nx); } vdv_sum = 0; int nx; if (v_v.rowNum() > 0) { /*--- for efficiency don't use get_v and get_dv ---*/ const double *v_arr = v_v.point(); if (av_dv.size() <= 0) { throw new AzException("AzReg_Tsrbase::update", "no dv?"); } const double *dv_arr = av_dv.point(focus_nx)->point(); for (nx = 0; nx < tree->nodeNum(); ++nx) { double v = v_arr[nx]; double dv = dv_arr[nx]; int depth = tree->node(nx)->depth; vdv_sum += reg_depth->apply(v * dv, depth); } } else { for (nx = 0; nx < tree->nodeNum(); ++nx) { double v = get_v(nx); double dv = get_dv(nx); int depth = tree->node(nx)->depth; vdv_sum += reg_depth->apply(v * dv, depth); } } dv2_sum = get_dv2_sum(); dr += vdv_sum; ddr += dv2_sum; }
/*--------------------------------------------------------*/ double AzReg_Tsrbase::penalty() const { double r = 0; int nx; for (nx = 0; nx < tree->nodeNum(); ++nx) { double v = get_v(nx); r += reg_depth->apply(v*v/2, tree->node(nx)->depth); } if (forNewLeaf) { checkLeaf("penalty"); double v = get_newleaf_v(); double rr = 2*reg_depth->apply(v*v/2, get_newleaf_depth()); /* 2* for siblings */ r += rr; } return r; }
/*--------------------------------------------------------*/ double AzReg_TsrSib::penalty_diff(const double leaf_w_delta[2]) const { checkLeaf("penalty_diff"); double diff = 0; /*--- on the existing nodes ---*/ double delsum = leaf_w_delta[0] + leaf_w_delta[1]; diff += vdv_sum * delsum; diff += (dv2_sum * (delsum*delsum) * 0.5); /*--- on the new leaf nodes ---*/ double leaf_v = (leaf_w_delta[0] - leaf_w_delta[1])/2; #if 0 diff += newleaf_dep_factor*leaf_v*leaf_v/2*2; /* "*2" for two leaves */ #else diff += newleaf_dep_factor*leaf_v*leaf_v; /* "/2" and "*2" (for two leaves) cancel out */ #endif return diff; }
/** * dr=sum_j v_j dv_j; ddr=sum_j dv_j^2 * v_j = bar_j - bar_{p(j)} where p(j) is j's parent. * * output: vdv_sum, dv2_sum, dr, ddr, and newleaf_dep_factor **/ void AzReg_TsrSib::update() { /* vdv_sum, dv2_sum: don't include new leaf nodes */ /* dr, ddr: include new leaf nodes */ if (focus_nx < 0) { throw new AzException("AzReg_TsrSib::update", "no focus node"); } dr = ddr = 0; if (forNewLeaf) { checkLeaf("update"); /*--- new leaf nodes: v=0, dv=0.5,-0.5 ---*/ double dv = 0.5; int depth = get_newleaf_depth(); newleaf_dep_factor = reg_depth->apply(1, depth); ddr += dv*dv*newleaf_dep_factor*2; /* *2 for two leaves */ } const AzSvect *v_dv = av_dv.point(focus_nx); const double *v_arr = v_v.point(); vdv_sum = dv2_sum = 0; if (doShortCut) { /* * Use the fact that v[s]+v[t] = 0, dv[s]+dv[t]=0 if s and t are siblings, * dv only depends on the distance from the leaf, and that * dv<>0 only for the ancestors and ancestors' siblings of the base leaf. */ double dv = 0.5; if (forNewLeaf) { dv = 0.25; } int nx = focus_nx; for ( ; ; ) { const AzTrTreeNode *np = tree->node(nx); int px = np->parent_nx; int depth = np->depth; double v = v_arr[nx]; if (depth == 0) { /* root */ dv *= 2; double dv_dep_factor = dv*reg_depth->apply(1, depth); vdv_sum += v*dv_dep_factor; dv2_sum += dv*dv_dep_factor; break; } else { double dv_dep_factor = dv*reg_depth->apply(1, depth); vdv_sum += 2*v*dv_dep_factor; /* *2 for the sibling */ dv2_sum += 2*dv*dv_dep_factor; /* *2 for the sibling */ } nx = px; dv /= 2; } } else { AzCursor cur; for ( ; ; ) { double dv; int nx = v_dv->next(cur, dv); if (nx < 0) break; double v = v_arr[nx]; int depth = tree->node(nx)->depth; double dv_dep_factor = dv*reg_depth->apply(1, depth); vdv_sum += v * dv_dep_factor; dv2_sum += dv * dv_dep_factor; } } dr += vdv_sum; ddr += dv2_sum; }
// if allkeys is set, stores all found keys there // if strongcheck is true, do full horizontal traversals for every node (slow) void checkCoid(COid startcoid, Set<I64> *allkeys, bool strongcheck){ Transaction *tx; tx = new Transaction(SC); LinkList<COidQueueElement> coidqueue; Set<COid> pastcoids; COidQueueElement *el, *elchild; COid coid; COid child; int res; Ptr<Valbuf> buf; i64 fencemin, fencemax; SuperValue *sv; el = new COidQueueElement(startcoid); el->fencemin = LLONG_MIN; el->fencemax = LLONG_MAX; coidqueue.pushTail(el); while (!coidqueue.empty()){ el = coidqueue.popHead(); coid = el->coid; fencemin = el->fencemin; fencemax = el->fencemax; delete el; if (pastcoids.belongs(coid)){ printf("COid %016llx:%016llx referenced more than once\n", (long long)coid.cid, (long long)coid.oid); assert(0); } else pastcoids.insert(coid); // read coid res = tx->vsuperget(coid, buf, 0, 0); assert(res==0); if (buf->type==0){ printf("COid %llx:%llx not a supervalue\n", (long long)coid.cid, (long long)coid.oid); assert(0); continue; } sv = buf->u.raw; checkNodeFence(coid, sv, fencemin, fencemax); checkNodeMonot(sv); checkHorizontal(tx, coid, 0, strongcheck); checkHorizontal(tx, coid, 1, strongcheck); if (sv->Attrs[DTREENODE_ATTRIB_FLAGS] & DTREENODE_FLAG_LEAF){ // this is a leaf node checkLeaf(coid, sv, allkeys); } else { // this is an inner node checkInner(coid, sv); } if (!(sv->Attrs[DTREENODE_ATTRIB_FLAGS] & DTREENODE_FLAG_LEAF)){ // add children to queue child.cid = coid.cid; for (int i=0; i < sv->Ncells; ++i){ child.oid = sv->Cells[i].value; elchild = new COidQueueElement(child); if (sv->CellType == 0){ // intkey if (i==0) elchild->fencemin = fencemin; else elchild->fencemin = sv->Cells[i-1].nKey; elchild->fencemax = sv->Cells[i].nKey; } else { // checking functionality is disabled for non-intkey trees, so just set fences to 0 elchild->fencemin = elchild->fencemax = 0; } coidqueue.pushTail(elchild); } // now add the last pointer child.oid = sv->Attrs[DTREENODE_ATTRIB_LASTPTR]; elchild = new COidQueueElement(child); if (sv->CellType == 0){ // intkey if (sv->Ncells >= 1) elchild->fencemin = sv->Cells[sv->Ncells-1].nKey; else elchild->fencemin = fencemin; elchild->fencemax = fencemax; } else { elchild->fencemin = elchild->fencemax = 0; } coidqueue.pushTail(elchild); } } delete tx; }