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

dag_delta.cc

Go to the documentation of this file.
00001 // DAG Delta implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2001-2003 Hermann Schichl
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 #include <dag_delta.h>
00028 
00029 void dag_delta::help_apply_p(work_node& x, model::walker& _x, model* nm) const
00030 {
00031   model::walker _w;
00032   unsigned int nn;
00033   std::vector<model::walker> __v;
00034 
00035   nn = _x->node_num; 
00036   while(_x.n_parents() > 0)
00037   {
00038     _w = _x << _x.parent_begin();
00039     if(_w == nm->ground())
00040       return; // nothing to do here
00041     nm->remove_edge_and_deattach(_w, _x);
00042     __v.push_back(_w);
00043   }
00044   _w = x.get_model_ptr()->node(nn);
00045   for(std::vector<model::walker>::iterator __m = __v.begin(); __m != __v.end();
00046       ++__m)
00047     x.get_model_ptr()->add_edge_back(*__m, _w);
00048 }
00049 
00050 void dag_delta::help_apply_s(work_node& x, model* nm) const
00051 {
00052   model::walker _w, _x(nm->sky());
00053   std::vector<model::walker> __v;
00054 
00055   while(_x.n_parents() > 0)
00056   {
00057     _w = _x << _x.parent_begin();
00058     if(_w == nm->ground())
00059       return; // nothing to do here
00060     nm->remove_edge_and_deattach(_w, _x);
00061     __v.push_back(_w);
00062   }
00063   for(std::vector<model::walker>::iterator __m = __v.begin(); __m != __v.end();
00064       ++__m)
00065     x.get_model_ptr()->add_edge_back(*__m, x.get_model_ptr()->sky());
00066 }
00067 
00068 void dag_delta::help_apply_c(work_node& x, model::walker& _x, model* nm) const
00069 {
00070   model::walker _w;
00071   unsigned int nn;
00072   std::vector<model::walker> __v;
00073 
00074   nn = _x->node_num; 
00075   while(_x.n_children() > 0)
00076   {
00077     _w = _x << _x.child_begin();
00078     if(_w == nm->sky())
00079       return; // nothing to do here
00080     nm->remove_edge_and_deattach(_x, _w);
00081     __v.push_back(_w);
00082   }
00083   _w = x.get_model_ptr()->node(nn);
00084   for(std::vector<model::walker>::iterator __m = __v.begin(); __m != __v.end();
00085       ++__m)
00086     x.get_model_ptr()->add_edge_back(_w, *__m);
00087 }
00088 
00089 void dag_delta::help_apply_g(work_node& x, model* nm) const
00090 {
00091   model::walker _w, _x(nm->ground());
00092   std::vector<model::walker> __v;
00093 
00094   while(_x.n_children() > 0)
00095   {
00096     if(_w == nm->sky())
00097       return; // nothing to do here
00098     _w = _x >> _x.child_begin();
00099     nm->remove_edge_and_deattach(_x, _w);
00100     __v.push_back(_w);
00101   }
00102   for(std::vector<model::walker>::iterator __m = __v.begin(); __m != __v.end();
00103       ++__m)
00104     x.get_model_ptr()->add_edge_back(x.get_model_ptr()->ground(), *__m);
00105 }
00106 
00107 bool dag_delta::apply(work_node& x, undelta_base*& u) const
00108 { 
00109   model::walker _x;
00110   unsigned int nn;
00111 
00112   if(is_full_delta)
00113   {
00114     if(!new_constraints.get() || new_constraints->empty()) return true;
00115     
00116     model* nm = new model(*new_constraints);
00117     gptr<model>* old_model = x._m;
00118 
00119     x._m = new ptr<model>(nm);
00120     x.make_node_ranges(false);
00121     x.init_cnumbers();
00122     u = (undelta_base*) new dag_undelta(old_model);
00123     return true;
00124   }
00125   else
00126   {
00127     dag_undelta *uu;
00128     model* xm = x.get_model_ptr();
00129     model* nm(NULL);
00130     u = (undelta_base*) (uu = new dag_undelta(false));
00131 
00132     if(new_constraints.get() && !new_constraints->empty())
00133     {
00134       nm = new model(xm->gid_data(), *new_constraints);
00135       // first add the new constraints
00136       // we do not duplicate all nodes in new_constraints
00137       // we rather remove all the edges to the ghost nodes and
00138       // replace them with edges to the real nodes.
00139       for(model::ref_iterator __x = nm->ghost_begin();
00140           __x != nm->ghost_end(); ++__x)
00141       {
00142         _x = *__x;
00143         // change the f_bounds according to the ghosts and keep old bounds
00144         if(!_x->f_bounds.is_entire())
00145         {
00146           uu->bounds_chgd[_x->node_num] = xm->node(_x->node_num)->f_bounds;
00147           xm->node(_x->node_num)->f_bounds.intersect(_x->f_bounds);
00148         }
00149         help_apply_p(x, _x, nm);
00150         help_apply_c(x, _x, nm);
00151       }
00152       help_apply_s(x, nm);
00153       help_apply_g(x, nm);
00154 
00155       x.reset_node_ranges();
00156       
00157       uu->added_nodes = nm->node_ref;
00158       uu->added_constraints = nm->constraints;
00159       std::sort(uu->added_constraints.begin(), uu->added_constraints.end(),
00160                 model::__docompare_nodes());
00161       uu->added_ghosts = nm->ghost_ref;
00162       uu->added_vars = nm->var_ref;
00163 
00164       // transfer node refs
00165       std::vector<model::walker>& nr(xm->node_ref);
00166       nn = nr.size();
00167       nr.insert(nr.end(), nm->node_ref.begin(), nm->node_ref.end());
00168       inplace_merge(nr.begin(), nr.begin()+nn, nr.end(),
00169                     model::__docompare_nodes());
00170       
00171       // transfer variable refs
00172       std::vector<model::walker>& vr(xm->var_ref);
00173       nn = vr.size();
00174       vr.insert(vr.end(), nm->var_ref.begin(), nm->var_ref.end());
00175       inplace_merge(vr.begin(), vr.begin()+nn, vr.end(),
00176                     model::__docompare_variables());
00177       
00178       // transfer ghost refs
00179       std::vector<model::walker>& gr(xm->ghost_ref);
00180       nn = gr.size();
00181       gr.insert(gr.end(), nm->ghost_ref.begin(), nm->ghost_ref.end());
00182       inplace_merge(gr.begin(), gr.begin()+nn, gr.end(),
00183                     model::__docompare_nodes());
00184       
00185       xm->constraints.insert(xm->constraints.end(), nm->constraints.begin(),
00186                              nm->constraints.end());
00187 
00188       /***********************************************************
00189        *
00190        * ATTENTION: Here the proper change of lin, matd, and mati
00191        *            is still missing!
00192        *
00193        ***********************************************************/
00194     }
00195 
00196     if(!rm_nodes.empty())
00197     {
00198       model::erased_part me = xm->erase_minimal_subgraph(rm_nodes);
00199       uu->rm_dag = new model(xm->gid_data(), me);
00200       uu->rm_e = me.second;
00201 
00202       // remove the elements taken out from the arrays
00203       std::vector<walker> _nn;
00204       std::swap(_nn, xm->node_ref);
00205       std::set_difference(_nn.begin(), _nn.end(), uu->rm_dag->node_ref.begin(),
00206                           uu->rm_dag->node_ref.end(),
00207                           back_inserter(xm->node_ref),
00208                           model::__docompare_nodes());
00209 
00210       _nn.erase(_nn.begin(), _nn.end());
00211       std::swap(_nn, xm->var_ref);
00212       std::set_difference(_nn.begin(), _nn.end(), uu->rm_dag->var_ref.begin(),
00213                           uu->rm_dag->var_ref.end(), back_inserter(xm->var_ref),
00214                           model::__docompare_variables());
00215 
00216       _nn.erase(_nn.begin(), _nn.end());
00217       std::swap(_nn, xm->ghost_ref);
00218       std::set_difference(_nn.begin(), _nn.end(), uu->rm_dag->ghost_ref.begin(),
00219                           uu->rm_dag->ghost_ref.end(),
00220                           back_inserter(xm->ghost_ref),
00221                           model::__docompare_nodes());
00222 
00223       // get rid of the constraints taken out
00224       std::vector<walker>::iterator _i =
00225            std::stable_partition(xm->constraints.begin(), xm->constraints.end(),
00226                      __check_nodes(uu->rm_dag->node_ref));
00227       std::copy(_i, xm->constraints.end(), uu->rm_dag->constraints.end());
00228       xm->constraints.erase(_i, xm->constraints.end());
00229 
00230       /***********************************************************
00231        *
00232        * ATTENTION: Here the proper change of lin, matd, and mati
00233        *            is still missing!
00234        *
00235        ***********************************************************/
00236 
00237       x.reset_node_ranges();
00238     }
00239     else if(nm)
00240       uu->rm_dag = new model(xm->gid_data());
00241 
00242     if(nm)
00243     {
00244       uu->rm_dag->objective = xm->objective;
00245       if(!nm->is_empty(nm->objective))
00246         xm->objective = nm->objective;
00247         
00248       uu->rm_dag->ocoeff = xm->ocoeff;
00249       if(nm->ocoeff != MAXINT)
00250         xm->ocoeff = nm->ocoeff;
00251     }
00252 
00253     x.make_node_ranges(true);
00254     x.init_cnumbers();
00255     return true;
00256   }
00257 }
00258 
00259 bool dag_undelta::unapply(work_node& x) const
00260 {
00261   if(is_full_undelta)
00262   {
00263     x._m = old_model;
00264     x.make_node_ranges(false);
00265     x.init_cnumbers();
00266     return true;
00267   }
00268   else
00269   {
00270     model* xm = x.get_model_ptr();
00271 
00272     // restore deleted parts
00273     std::vector<model::enhanced_edge>::const_iterator eei, eee(rm_e.end());
00274 
00275     // reconstruct edges
00276     for(eei = rm_e.begin(); eei != eee; ++eei)
00277     {
00278       if((*eei).second)
00279       {
00280         if((*eei).first.second.is_root())
00281           xm->remove_edge(xm->ground(), (*eei).first.second);
00282         if((*eei).first.first.is_leaf())
00283           xm->remove_edge((*eei).first.first, xm->sky());
00284       }
00285       xm->add_edge_back((*eei).first.first, (*eei).first.second);
00286     }
00287     // now we detach all nodes from rm_dag
00288     if(rm_dag.get() && !rm_dag->empty())
00289     {
00290       model::walker _sg(rm_dag->sky());
00291       for(model::parents_iterator _w = _sg.parent_begin();
00292           _w != _sg.parent_end(); ++_w)
00293         rm_dag->remove_edge_and_deattach(_sg << _w, _sg);
00294       _sg = rm_dag->ground();
00295       for(model::children_iterator _w = _sg.child_begin();
00296           _w != _sg.child_end(); ++_w)
00297         rm_dag->remove_edge_and_deattach(_sg, _sg >> _w);
00298       rm_dag->add_edge_back(rm_dag->ground(), rm_dag->sky());
00299     }
00300 
00301     // first correct all global references
00302     std::vector<model::walker>::const_iterator __x, __e;
00303     for(__x = added_nodes.begin(), __e = added_nodes.end(); __x != __e; ++__x)
00304       xm->gid_data()->mk_globref((*__x)->node_num, xm->empty_reference());
00305     for(__x = added_vars.begin(), __e = added_vars.end(); __x != __e; ++__x)
00306       xm->gid_data()->mk_gvarref((*__x)->params.nn(), xm->empty_reference());
00307     unsigned int const_num;
00308     for(__x = added_constraints.begin(), __e = added_constraints.end();
00309         __x != __e; ++__x)
00310     {
00311       bool ok = xm->gid_data()->get_const_num((*__x)->node_num, const_num);
00312       if(ok)
00313         xm->gid_data()->remove_const_ref(const_num);
00314     }
00315     
00316     // remove all previously added nodes
00317     model::erased_part me = xm->erase_minimal_subgraph(added_nodes);
00318     xm->clear_erased_part(me);
00319 
00320     if(!added_nodes.empty())
00321     {
00322       // remove the elements previously added
00323       std::vector<walker> _nn;
00324       std::swap(_nn, xm->node_ref);
00325       std::set_difference(_nn.begin(), _nn.end(), added_nodes.begin(),
00326                           added_nodes.end(), back_inserter(xm->node_ref),
00327                           model::__docompare_nodes());
00328     }
00329 
00330     std::vector<model::walker> _nn;
00331     if(!added_vars.empty())
00332     {
00333       _nn.erase(_nn.begin(), _nn.end());
00334       std::swap(_nn, xm->var_ref);
00335       std::set_difference(_nn.begin(), _nn.end(), added_vars.begin(),
00336                           added_vars.end(), back_inserter(xm->var_ref),
00337                           model::__docompare_variables());
00338     }
00339 
00340     if(!added_ghosts.empty())
00341     {
00342       _nn.erase(_nn.begin(), _nn.end());
00343       std::swap(_nn, xm->ghost_ref);
00344       std::set_difference(_nn.begin(), _nn.end(), added_ghosts.begin(),
00345                           added_ghosts.end(), back_inserter(xm->ghost_ref),
00346                           model::__docompare_nodes());
00347     }
00348 
00349     if(!added_constraints.empty())
00350     {
00351       // get rid of the constraints previously added
00352       std::vector<walker>::iterator _i =
00353            std::stable_partition(xm->constraints.begin(), xm->constraints.end(),
00354                                  __check_walkers(added_constraints));
00355       xm->constraints.erase(_i, xm->constraints.end());
00356     }
00357     
00358     // restore the old f_bounds of all changed nodes
00359     for(std::map<unsigned int, interval>::const_iterator __b = 
00360         bounds_chgd.begin(); __b != bounds_chgd.end(); ++__b)
00361       xm->node(__b->first)->f_bounds = __b->second;
00362 
00363     return true;
00364   }
00365 }

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