Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

search_graph.cc

Go to the documentation of this file.
00001 // Search Graph implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2001-2003 Hermann Schichl, Evgueni Petrov, Brice Pajot
00004 //
00005 // This file is part of the COCONUT API.  This library
00006 // is free software; you can redistribute it and/or modify it under the
00007 // terms of the Library GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // Library GNU General Public License for more details.
00015 
00016 // As a special exception, you may use this file as part of a free software
00017 // library without restriction.  Specifically, if other files instantiate
00018 // templates or use macros or inline functions from this file, or you compile
00019 // this file and link it with other files to produce an executable, this
00020 // file does not by itself cause the resulting executable to be covered by
00021 // the Library GNU General Public License.  This exception does not however
00022 // invalidate any other reasons why the executable file might be covered by
00023 // the Library GNU General Public License.
00024 
00027 // FIXED by IRIN as of 08/11/2002
00028 // + re-ordered and/or completed some initialization lists
00029 // + made some methods of search_node, full_node etc. "const"
00030 // + suppressed some empty declarations
00031 // + made the destructors of search_node & Co. "virtual" 
00032 //
00033 
00034 #include <search_graph.h>
00035 
00036 using namespace vgtl;
00037 using namespace std;
00038 
00039 #include "sum_deltas.h"
00040 
00041 search_focus& search_graph::new_focus(const search_inspector& where)
00042 {
00043   search_inspector where_copy = where;
00044   walker focus_to_add((node_type *) where_copy.node());
00045 
00046   if(find(focus.begin(), focus.end(), focus_to_add) != focus.end())
00047     throw search_graph_exception
00048       ("in search_graph :: new_focus : the inspected node is already focused");
00049   focus.push_front(focus_to_add);
00050   return focus.front();
00051 }
00052 
00053 void search_graph::destroy_focus(const search_focus& where)
00054 {
00055   list<walker>::iterator i = find(focus.begin(), focus.end(), where);
00056   if(i == focus.end())
00057     throw search_graph_exception
00058         ("in search_graph :: destroy_focus (...) : the focus does not exist");
00059   focus.erase(i);
00060 }
00061 
00062 search_focus& search_graph::set_focus(search_focus& focus_to_replace,
00063                                       const search_inspector& where)
00064 {
00065   list<walker>::iterator i =
00066       find(focus.begin(), focus.end(), focus_to_replace);
00067   if(i == focus.end())
00068     throw search_graph_exception
00069         ("in search_graph :: set_focus (...) : the focus does not exist");
00070   search_inspector where_copy = where;
00071 
00072   *i = walker((node_type *) where_copy.node());
00073   return *i;
00074 }
00075 
00076 search_inspector& search_graph::new_inspector(const search_inspector &
00077                                                         inspector_to_add)
00078 {
00079   list<const_walker>::iterator i =
00080       find(inspector.begin(), inspector.end(), inspector_to_add);
00081   if(i != inspector.end())
00082     return *i;
00083   inspector.push_front(inspector_to_add);
00084   return inspector.front();
00085 }
00086 
00087 void search_graph::destroy_inspector(const search_inspector &
00088                                                 inspector_to_destroy)
00089 {
00090   list<const_walker>::iterator i =
00091       find(inspector.begin(), inspector.end(), inspector_to_destroy);
00092   if(i == inspector.end())
00093     throw search_graph_exception
00094       ("in search_graph :: destroy_inspector (...) : the inspector does not exist");
00095   inspector.erase(i);
00096 }
00097 
00098 work_node search_graph::extract(const search_inspector & where)
00099 {
00100   list<const_walker>::iterator i =
00101       find(inspector.begin(), inspector.end(), where);
00102   if(i == inspector.end())
00103     throw search_graph_exception
00104         ("in search_graph :: extract (...) : the inspector does not exist");
00105   work_node *result = recursive_walk_up_if(where, sum_deltas(ptr_ground));
00106   work_node where_as_work_node(*result);
00107   where_as_work_node._snr = (*where)->parent_relation();
00108   delete result;
00109 
00110   return where_as_work_node;
00111 }
00112 
00113 work_node search_graph::extract(const search_focus & where)
00114 {
00115   list<walker>::iterator i =
00116       find(focus.begin(), focus.end(), where);
00117   if(i == focus.end())
00118     throw search_graph_exception
00119         ("in search_graph :: extract (...) : the focus does not exist");
00120   work_node *result = recursive_walk_up_if(where, sum_deltas(ptr_ground));
00121   work_node where_as_work_node(*result);
00122   where_as_work_node._snr = (*where)->parent_relation();
00123   delete result;
00124 
00125   return where_as_work_node;
00126 }
00127 
00128 search_inspector& search_graph::insert(const search_focus &where,
00129                                        const search_node &what)
00130 {
00131   search_focus protected_where(where);
00132   walker new_where =
00133       split(protected_where, protected_where.child_begin(), sky(),
00134             sky().parent_begin(), (search_node*) &what);
00135 
00136   const_walker new_where_as_const_walker((node_type*) new_where.node());
00137 
00138   inspector.push_front(new_where_as_const_walker);
00139   return inspector.front();
00140 }
00141 
00142 search_inspector& search_graph::replace(search_focus& where,
00143                                         const search_node &what)
00144 {
00145   list<walker>::iterator i = find(focus.begin(), focus.end(), where);
00146   if(i == focus.end())
00147     throw search_graph_exception
00148         ("in search_graph :: replace (...) : the focus does not exist");
00149   *where = (search_node*) &what;
00150   inspector.push_front(const_walker((node_type*) where.node()));
00151   return inspector.front();
00152 }
00153 
00154 void search_graph::_internal_remove(search_focus& where)
00155 {
00156   if((*where)->is_delta())
00157   {                             // removing a delta_node : 
00158     delta_node& where_as_delta = *(delta_node*) *where;   // cast to delta_node
00159     if(!where.is_leaf())
00160     {
00161       for(walker::children_iterator c = where.child_begin();
00162           c != where.child_end(); ++c)
00163         if((*(where >> c))->is_delta())
00164         {
00165           // cast to delta_node *
00166           delta_node*& c_as_delta = (delta_node*) *(where >> c);
00167 
00168           vector<delta_id> delta_where_plus_delta_c;
00169           for(unsigned int i = 0; i < where_as_delta.n_deltas(); ++i)
00170           {
00171             db_deltas_to_remove.push_front(where_as_delta.get_delta_id(i));
00172             delta_where_plus_delta_c.push_back(db_deltas_to_remove.front());
00173           }
00174           for(unsigned int i = 0; i < c_as_delta->n_deltas(); ++i)
00175           {
00176             db_deltas_to_remove.push_front(c_as_delta->get_delta_id(i));
00177             delta_where_plus_delta_c.push_back(db_deltas_to_remove.front());
00178           }
00179           gptr<vdbl::database>* _xdb = c_as_delta->database();
00180           delete c_as_delta;
00181           for(list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00182               i != search_nodes_to_deallocate.end(); ++i)
00183             if(c_as_delta == *i)
00184             {
00185               search_nodes_to_deallocate.erase(i);
00186               break;
00187             }
00188 
00189           c_as_delta = new delta_node(get_node_id(), __dbuser,
00190                                       delta_where_plus_delta_c, ptr_ground,
00191                                       *_xdb);
00192           search_nodes_to_deallocate.push_front(c_as_delta);
00193         }
00194     }
00195   }
00196   else
00197   {                             // removing a full_node :
00198     full_node& where_as_full = *(full_node*) *where; // cast to full_node
00199     if(!where.is_leaf())
00200     {
00201       for(walker::children_iterator c = where.child_begin();
00202           c != where.child_end(); ++c)
00203         if((*(where >> c))->is_delta())
00204         {
00205           delta_node *&c_as_delta = (delta_node*) *(where >> c);  // cast to delta_node *
00206           work_node full_where_plus_delta_c(full_node_to_work_node
00207                                             (where_as_full, ptr_ground));
00208           for(unsigned int i = 0; i < c_as_delta->n_deltas(); ++i)
00209             full_where_plus_delta_c += c_as_delta->get_delta_id(i);
00210           delete *(where >> c);
00211           for(list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00212               i != search_nodes_to_deallocate.end(); ++i)
00213             if(*(where >> c) == *i)
00214             {
00215               search_nodes_to_deallocate.erase(i);
00216               break;
00217             }
00218 
00219           *(where >> c) = new work_node(full_where_plus_delta_c);
00220           search_nodes_to_deallocate.push_front(*(where >> c));
00221         }
00222     }
00223   }
00224   // now take care for promoting the erase information properly
00225   // especially the information in _snr is important
00226   if((*where)->parent_relation() == snr_split)
00227   {
00228     if(where.n_parents() > 1)
00229       throw search_graph_exception
00230         ("in search_graph :: remove (...) : a split has more than one parent");
00231     else
00232     {
00233       walker::parents_iterator p = where.parent_begin();
00234       walker parent_of_where = where << p;
00235       unsigned int num_of_splits(0);
00236       walker first_split;
00237       for(walker::children_iterator c = parent_of_where.child_begin();
00238           c != parent_of_where.child_end(); ++c)
00239       {
00240         walker child_of_parent_of_where = parent_of_where >> c;
00241         if(child_of_parent_of_where != where &&
00242           (*child_of_parent_of_where)->parent_relation() == snr_split)
00243         {
00244           if(num_of_splits == 0)
00245             first_split = child_of_parent_of_where;
00246           num_of_splits++;
00247         }
00248       }
00249       if(num_of_splits == 1)  // a single split is a reduction
00250         (*first_split)->_snr = snr_reduction;
00251     }
00252   }
00253 
00254   delete *where;
00255   for(list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00256       i != search_nodes_to_deallocate.end(); ++i)
00257     if(*where == *i)
00258     {
00259       search_nodes_to_deallocate.erase(i);
00260       break;
00261     }
00262 
00263   erase(where);
00264   return;
00265 }
00266 
00267 void search_graph::remove(search_focus& where)
00268 {
00269   list<walker>::iterator flw = find(focus.begin(), focus.end(), where);
00270   if(flw == focus.end())
00271     throw search_graph_exception
00272         ("in search_graph :: remove (...) : the focus does not exist");
00273   if(where.n_parents() >= 2 && (*where)->parent_relation() != snr_glue)
00274     throw search_graph_exception
00275         ("in search_graph :: remove (...) : search_node has several ancestors");
00276   _internal_remove(where);
00277 }
00278 
00279 search_focus& search_graph::promote(search_focus& where)
00280 {
00281   list<walker>::iterator i = find(focus.begin(), focus.end(), where);
00282   if(i == focus.end())
00283     throw search_graph_exception
00284         ("in search_graph :: promote (...) : the focus does not exist");
00285   if(where.n_parents() >= 2)
00286     throw search_graph_exception
00287         ("in search_graph :: promote (...) : search_node has several ancestors");
00288   walker p = where << where.parent_begin();
00289 
00290   if((*where)->is_delta())
00291   {                             // promoting a delta_node :
00292     delta_node *where_as_delta = (delta_node*) *where;  // cast to delta_node *
00293 
00294     if((*p)->is_delta())
00295     {
00296       delta_node* p_as_delta = (delta_node*) *p;
00297 
00298       vector<delta_id> delta_where_plus_delta_p;
00299       for(unsigned int i = 0; i < where_as_delta->n_deltas(); ++i)
00300       {
00301         db_deltas_to_remove.push_front(where_as_delta->get_delta_id(i));
00302         delta_where_plus_delta_p.push_back(db_deltas_to_remove.front());
00303       }
00304       for(unsigned int i = 0; i < p_as_delta->n_deltas(); ++i)
00305       {
00306         db_deltas_to_remove.push_front(p_as_delta->get_delta_id(i));
00307         delta_where_plus_delta_p.push_back(db_deltas_to_remove.front());
00308       }
00309       gptr<vdbl::database>* _xdb = p_as_delta->database();
00310       delete *p;
00311       for(list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00312           i != search_nodes_to_deallocate.end(); ++i)
00313         if(*p == *i)
00314         {
00315           search_nodes_to_deallocate.erase(i);
00316           break;
00317         }
00318 
00319       *p = new delta_node(get_node_id(), __dbuser, delta_where_plus_delta_p,
00320                           ptr_ground, *_xdb);
00321     }
00322     else
00323     {
00324       full_node *p_as_full = (full_node*) *p;            // cast to full_node
00325       work_node full_p_plus_delta_where(full_node_to_work_node
00326                                                 (*p_as_full, ptr_ground));
00327 
00328       for(unsigned int i = 0; i < where_as_delta->n_deltas(); ++i)
00329         full_p_plus_delta_where += where_as_delta->get_delta_id(i);
00330       delete *p;
00331       for(list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00332           i != search_nodes_to_deallocate.end(); ++i)
00333         if(*p == *i)
00334         {
00335           search_nodes_to_deallocate.erase(i);
00336           break;
00337         }
00338 
00339       *p = new work_node(full_p_plus_delta_where);
00340     }
00341     search_nodes_to_deallocate.push_front(*p);
00342   }
00343   else
00344   {                             // promoting a full_node :
00345     delete *p;
00346     for(list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00347         i != search_nodes_to_deallocate.end(); ++i)
00348       if(*p == *i)
00349       {
00350         search_nodes_to_deallocate.erase(i);
00351         break;
00352       }
00353 
00354     *p = *where;
00355   }
00356   *i = p;
00357   delete *where;
00358   for(list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00359       i != search_nodes_to_deallocate.end(); ++i)
00360     if(*where == *i)
00361     {
00362       search_nodes_to_deallocate.erase(i);
00363       break;
00364     }
00365 
00366   erase(where);
00367   return *i;
00368 }
00369 
00370 void search_graph::remove_upwards(search_focus& where, bool relaxation_kills)
00371 {
00372   list<walker>::iterator flw = find(focus.begin(), focus.end(), where);
00373   if(flw == focus.end())
00374     throw search_graph_exception
00375         ("in search_graph :: remove_upwards (...) : the focus does not exist");
00376   if(where.n_parents() >= 2 && (*where)->parent_relation() != snr_glue)
00377     throw search_graph_exception
00378         ("in search_graph :: remove_upwards (...) : search_node has several ancestors");
00379 
00380   list<walker> to_be_erased;
00381   to_be_erased.push_front(*flw);
00382 
00383   for(flw = to_be_erased.begin(); flw != to_be_erased.end(); ++flw)
00384   {
00385     switch((**flw)->parent_relation())
00386     {
00387       case snr_root:
00388         // this cleans the whole search graph, so no need to do anything
00389         break;
00390       case snr_split:
00391         // removing splits does not traverse upwards
00392         break;
00393       case snr_relaxation:
00394         if(!relaxation_kills)
00395           break;
00396         // no break intentionally
00397       case snr_reduction:
00398       case snr_glue:
00399         // all parents have to vanish, as well
00400         for(walker::parents_iterator p = (*flw).parent_begin();
00401             p != (*flw).parent_end(); ++p)
00402           to_be_erased.push_back((*flw) << p);
00403         break;
00404       case snr_worknode:
00405       case snr_virtual:
00406         throw search_graph_exception
00407           ("in search_graph :: remove_upwards (...) : search_node is unremovable!");
00408         break;
00409       default:
00410         throw search_graph_exception
00411           ("in search_graph :: remove_upwards (...) : search_node has unknown parent relation!");
00412         break;
00413     }
00414     _internal_remove(*flw);
00415   }
00416 }
00417 

Generated on Tue Nov 4 01:57:58 2003 for COCONUT API by doxygen1.2.18