// return all p3 in p3_set with (*,*,v) set<t_3path> t_dir_graph::get_p3_by_third(const t_vertex& v) const{ set<t_vertex> pred, predpred; set<t_3path> result; pred = get_predecessors(v); for(set<t_vertex>::const_iterator u = pred.begin(); u!= pred.end(); u++){ predpred = get_predecessors(*u); for(set<t_vertex>::const_iterator w = predpred.begin(); w!= predpred.end(); w++) if(p3_set.find(t_3path(t_arc(*w,*u),t_arc(*u,v))) != p3_set.end()) result.insert(t_3path(t_arc(*w,*u),t_arc(*u,v))); } return result; }
// mark an arc forbidden/permanent, // note that, if adjacent arcs are also forbidden/permanent, this mark may cascade bool t_dir_graph::mark_arc(const t_arc& a, const uint mark){ if(successors.find(a.first) == successors.end()) return false; // dont mark edges that are not in VxV if(successors.find(a.second) == successors.end()) return false; // dont mark edges that are not in VxV dbgcout << "marking " << a << (mark==MRK_NONE?"none":(mark==MRK_FORBIDDEN?"forbidden":"permanent")) << "\n"; bool result = true; switch(mark){ case MRK_NONE: return (forbidden_arcs.erase(a) || permanent_arcs.erase(a)); break; case MRK_FORBIDDEN: if((!contains_arc(a)) && (forbidden_arcs.find(a) == forbidden_arcs.end()) && forbidden_arcs.insert(a).second) { set<t_vertex> belt = set_intersect(get_successors(a.first), get_predecessors(a.second)); for(set<t_vertex>::iterator u = belt.begin(); u != belt.end(); u++){ if(permanent_arcs.find(t_arc(a.first, *u)) != permanent_arcs.end()) result &= mark_arc(t_arc(*u, a.second), MRK_FORBIDDEN); if(permanent_arcs.find(t_arc(*u, a.second)) != permanent_arcs.end()) result &= mark_arc(t_arc(a.first, *u), MRK_FORBIDDEN); } return result; } else return false; break; case MRK_PERMANENT: if(contains_arc(a) && (permanent_arcs.find(a) == permanent_arcs.end()) && permanent_arcs.insert(a).second) { set<t_vertex> pred = get_predecessors(a.first); for(set<t_vertex>::iterator u = pred.begin(); u != pred.end(); u++){ if(permanent_arcs.find(t_arc(*u, a.first)) != permanent_arcs.end()) result &= mark_arc(t_arc(*u, a.second), MRK_PERMANENT); } pred = set_substract(get_vertices(), get_predecessors(a.second)); for(set<t_vertex>::iterator u = pred.begin(); u != pred.end(); u++){ if(forbidden_arcs.find(t_arc(*u, a.second)) != forbidden_arcs.end()) result &= mark_arc(t_arc(*u, a.second), MRK_FORBIDDEN); } set<t_vertex> succ = get_successors(a.second); for(set<t_vertex>::iterator u = succ.begin(); u != succ.end(); u++){ if(permanent_arcs.find(t_arc(a.second, *u)) != permanent_arcs.end()) result &= mark_arc(t_arc(a.first, *u), MRK_PERMANENT); } succ = set_substract(get_vertices(), get_successors(a.first)); for(set<t_vertex>::iterator u = succ.begin(); u != succ.end(); u++){ if(forbidden_arcs.find(t_arc(a.first, *u)) != forbidden_arcs.end()) result &= mark_arc(t_arc(a.second, *u), MRK_FORBIDDEN); } return result; } else return false; break; default: return false; } }
// return all p3 in p3_set with (*,v,*) set<t_3path> t_dir_graph::get_p3_by_middle(const t_vertex& v) const{ set<t_vertex> succ, pred; set<t_3path> result; succ = get_successors(v); pred = get_predecessors(v); for(set<t_vertex>::const_iterator u = pred.begin(); u!= pred.end(); u++) for(set<t_vertex>::const_iterator w = succ.begin(); w!= succ.end(); w++) if(p3_set.find(t_3path(t_arc(*u,v),t_arc(v,*w))) != p3_set.end()) result.insert(t_3path(t_arc(*u,v),t_arc(v,*w))); return result; }
// increase the belt size of the given diamond // O(log n) void t_dir_graph::increase_diamond(const t_diamond& diam){ map<t_diamond, uint>::iterator d_iter = diamond_set.find(diam); // cout << "increasing diamond-belt of "<<diam<<"\n"; if(d_iter != diamond_set.end()){ d_iter->second++; } else {// if its not there, maybe it should be inserted... // this intersection can be calced in O(1), otherwise, diam would have been in diamond_set ! set<t_vertex> belt = set_intersect(get_successors(diam.first), get_predecessors(diam.second)); // cout << "oops, not yet there, "<<diam<<" is "<<(belt.size()>1?"":"not ")<<"inserted (size "<<belt.size()<<")\n"; if(belt.size() > 1) diamond_set.insert(pair<t_diamond,uint>(diam, belt.size())); } }
// insert an arc // O(n log n) bool t_dir_graph::insert_arc(const t_arc& a, const bool permanent){ if(successors.find(a.second) == successors.end()) return false; // dont insert edges that are not in VxV if(predecessors.find(a.first) == predecessors.end()) return false; // dont insert edges that are not in VxV if(forbidden_arcs.find(a) != forbidden_arcs.end()) return false; // dont insert if the arc is forbidden t_adjtable::iterator i = successors.find(a.first); t_adjtable::iterator j = predecessors.find(a.second); if((i != successors.end()) && (j != predecessors.end())) if(i->second.insert(a.second).second) if(j->second.insert(a.first).second){ if(permanent) mark_arc(a, MRK_PERMANENT); // update p3_set and diamond_set // first, remove all p3 destroyed by a set<t_vertex> belt = set_intersect(i->second,j->second); for(set<t_vertex>::const_iterator u = belt.begin(); u != belt.end(); u++) p3_set.erase(t_3path(t_arc(a.first, *u),t_arc(*u, a.second))); diamond_set.erase(t_diamond(a.first, a.second)); // second, add new P3 and diamonds // u -> a.first -> a.second set<t_vertex> pred = set_substract(get_predecessors(a.first), j->second); pred.erase(a.second); for(set<t_vertex>::const_iterator u = pred.begin(); u != pred.end(); u++){ increase_diamond(t_diamond(*u, a.second)); p3_set.insert(t_3path(t_arc(*u,a.first),a)); } // a.first -> a.second -> u set<t_vertex> succ = set_substract(get_successors(a.second), i->second); succ.erase(a.first); for(set<t_vertex>::const_iterator u = succ.begin(); u != succ.end(); u++){ increase_diamond(t_diamond(a.first, *u)); p3_set.insert(t_3path(a,t_arc(a.second, *u))); } return true; } else {// avoid inconsistency i->second.erase(a.second); return false; } else return false; else return false; }
// calculate the reachability of v in D // if undirected is true, all vertices can reach their predecessors set<t_vertex> t_dir_graph::get_reachable(const t_vertex& v, bool undirected) const{ if(contains_vertex(v)){ set<t_vertex> to_check, checked, neighbors; t_vertex u; to_check.insert(v); while(!to_check.empty()){ u = *(to_check.begin()); to_check.erase(to_check.begin()); neighbors = get_successors(u); if(undirected) neighbors = set_unite(neighbors, get_predecessors(u)); neighbors = set_substract(neighbors, checked); to_check = set_unite(to_check, neighbors); checked.insert(u); } return checked; } else return set<t_vertex>(); }
// delete an arc // O(n log n) bool t_dir_graph::delete_arc(const t_arc& a, const bool forbidden){ if(permanent_arcs.find(a) != permanent_arcs.end()) return false; // dont delete if the arc is permanent t_adjtable::iterator i = successors.find(a.first); t_adjtable::iterator j = predecessors.find(a.second); if((i != successors.end()) && (j != predecessors.end())) if(i->second.erase(a.second)) if(j->second.erase(a.first)){ if(forbidden) mark_arc(a, MRK_FORBIDDEN); // update p3_set and diamond_set // first, remove all p3 destroyed by a // u -> a.first -> a.second set<t_vertex> pred = set_substract(get_predecessors(a.first), j->second); pred.erase(a.second); for(set<t_vertex>::const_iterator u = pred.begin(); u != pred.end(); u++){ decrease_diamond(t_diamond(*u,a.second)); p3_set.erase(t_3path(t_arc(*u,a.first),t_arc(a.first, a.second))); } // a.first -> a.second -> u set<t_vertex> succ = set_substract(get_successors(a.second), i->second); succ.erase(a.first); for(set<t_vertex>::const_iterator u = succ.begin(); u != succ.end(); u++){ decrease_diamond(t_diamond(a.first, *u)); p3_set.erase(t_3path(t_arc(a.first, a.second),t_arc(a.second, *u))); } // second, add new P3 and diamonds set<t_vertex> belt = set_intersect(i->second,j->second); for(set<t_vertex>::const_iterator u = belt.begin(); u != belt.end(); u++) p3_set.insert(t_3path(t_arc(a.first, *u),t_arc(*u, a.second))); if(belt.size()>1) diamond_set.insert( pair<t_diamond,uint>(t_diamond(a.first,a.second),belt.size()) ); return true; } else return false; else return false; else return false; }
// get all neighbors of v, that is successors and predecessors set<t_vertex> t_dir_graph::get_neighbors(const t_vertex& v) const{ return set_unite(get_predecessors(v), get_successors(v)); }
int main(int argc, char **argv) { char word[MAXWORDSIZE]; char cmd[MAXWORDSIZE]; /* string to hold a command */ char fname[MAXWORDSIZE]; /* name of input file */ PAGENO i; int goOn; int k; setparms(); /* reads the pagesize and the number of ptrs/postigs_record */ dbopen(); /* opens or creates the three files (btree, postings, text) */ goOn = TRUE; while (goOn) { printf("\n\t*** These are your commands .........\n"); printf("\t\"C\" to scan the tree\n"); printf("\t\"i\" to insert\n"); printf("\t\"p\" to print a btree page\n"); printf("\t\"s\" to search, and print the key\n"); printf("\t\"S\" to search, and print the key, posting list pairs\n"); printf("\t\">\" to print k successors\n"); printf("\t\"<\" to print k predecessors\n"); printf("\t\"T\" to print the btree in inorder format\n"); printf("\t\"#\" to reset and print stats\n"); printf("\t\"x\" to exit\n"); /* printf("\"d\" to display statistics, \"c\" to clear them,\n"); */ scanf("%s", cmd); assert(strlen(cmd) < MAXWORDSIZE); switch (cmd[0]) { case 'C': printf("\n*** Scanning... \n"); scanTree(&printOcc); break; case 'i': printf("\tgive input file name: "); scanf("%s", fname); assert(strlen(fname) < MAXWORDSIZE); printf("\n*** Inserting %s\n", fname); insert(fname); break; case 's': printf("enter search-word: "); scanf("%s", word); assert(strlen(word) < MAXWORDSIZE); printf("\n*** Searching for word %s \n", word); search(word, FALSE); break; case 'S': printf("enter search-word: "); scanf("%s", word); assert(strlen(word) < MAXWORDSIZE); printf("\n*** Searching for word %s \n", word); search(word, TRUE); break; case 'p': printf("pagenumber=?\n"); scanf("%s", cmd); assert(strlen(cmd) < MAXWORDSIZE); i = (PAGENO) atoi(cmd); printPage(i, fpbtree); break; case '>': printf("word=?\n"); scanf("%s", word); printf("k=?\n"); scanf("%d", &k); get_successors(word, k, NULL); break; case '<': printf("word=?\n"); scanf("%s", word); printf("k=?\n"); scanf("%d", &k); get_predecessors(word, k, NULL); break; case 'T': printf("\n*** Printing tree in order .........\n"); PrintTreeInOrder(ROOT, 0); break; case '#': printf("\n"); printFetchPageCnt(); printf("\n...reseted FetchPage counter\n"); break; case 'x': printf("\n*** Exiting .........\n"); goOn = FALSE; break; default: printf("\n*** Illegal command \"%s\"\n", cmd); break; } } dbclose(); return (0); }