00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00028 #include <coconut_config.h>
00029 #include <search_node.h>
00030 #include <infeasible_delta.h>
00031 #include <graphorder.h>
00032
00033 namespace coco {
00034
00035 work_node operator-(const work_node& _w, const delta_id& _d)
00036 {
00037 work_node _tmp(_w);
00038 std::map<delta_id,undelta>::iterator __f;
00039
00040 __f = _tmp.undeltas.find(_d);
00041 if(__f == _tmp.undeltas.end())
00042 {
00043 throw api_exception(apiee_internal,
00044 std::string("work_node -: Cannot unapply delta <")+convert_to_str(_d)+
00045 "> which was not previously applied to work node <"+
00046 convert_to_str(_tmp.get_id())+">!");
00047 }
00048 else
00049 {
00050 std::list<delta_id>::iterator __g, __e(_tmp.deltas.begin());
00051 bool found = false;
00052 for(__g = _tmp.deltas.end(); __g != __e;)
00053 {
00054 --__g;
00055 if(*__g == _d)
00056 {
00057 found = true;
00058 break;
00059 }
00060 }
00061 if(found)
00062 {
00063 if(__g == _tmp.deltanew_it)
00064 ++_tmp.deltanew_it;
00065 _tmp.deltas.erase(__g);
00066 }
00067 }
00068 if(!(*__f).second.unapply(_tmp, _d))
00069 std::cerr << "Warning: Could not unapply delta <" <<
00070 _d << "> to work node <" << _tmp.get_id() << ">!" << std::endl;
00071 else
00072 _tmp.undeltas.erase(__f);
00073 return _tmp;
00074 }
00075
00076 work_node& operator-=(work_node& _w, const delta_id& _d)
00077 {
00078 std::map<delta_id,undelta>::iterator __f;
00079
00080 __f = _w.undeltas.find(_d);
00081 if(__f == _w.undeltas.end())
00082 {
00083 throw api_exception(apiee_internal,
00084 std::string("work_node -=: Cannot unapply delta <")+convert_to_str(_d)+
00085 "> which was not previously applied to work node <"+
00086 convert_to_str(_w.get_id())+">!");
00087 }
00088 else
00089 {
00090 std::list<delta_id>::iterator __g, __e(_w.deltas.begin());
00091 bool found = false;
00092 for(__g = _w.deltas.end(); __g != __e;)
00093 {
00094 --__g;
00095 if(*__g == _d)
00096 {
00097 found = true;
00098 break;
00099 }
00100 }
00101 if(found)
00102 {
00103 if(__g == _w.deltanew_it)
00104 ++_w.deltanew_it;
00105 _w.deltas.erase(__g);
00106 }
00107 }
00108 if(!(*__f).second.unapply(_w, _d))
00109 std::cerr << "Warning: Could not unapply delta <" <<
00110 _d << "> to work node <" << _w.get_id() << ">!" << std::endl;
00111 else
00112 _w.undeltas.erase(__f);
00113 return _w;
00114 }
00115
00116 void work_node::init_all()
00117 {
00118 dtable = (vdbl::standard_table*)
00119 get_database_ptr()->get_table("deltas", get_dbuserid());
00120 if(dtable == NULL)
00121 {
00122 get_database_ptr()->create_table("deltas", get_dbuserid());
00123 dtable = (vdbl::standard_table*)
00124 get_database_ptr()->get_table("deltas", get_dbuserid());
00125 if(dtable == NULL)
00126 throw api_exception(apiee_internal,
00127 "work_node::work_node: Database inconsistency (deltas table)");
00128 dtable_id = get_database_ptr()->get_tableid("deltas", get_dbuserid());
00129 dtable->add_col("delta",vdbl::typed_col<delta>(delta(infeasible_delta())),
00130 vdbl::colflags());
00131 dtable->add_col("certificate",
00132 vdbl::typed_col<certificate>(certificate(no_certificate())),
00133 vdbl::colflags(true));
00134 vdbl::colid _c_id(dtable->get_col_id("delta"));
00135 dtable->add_col("action",
00136 vdbl::method_col<delta_get_action>(delta_get_action(_c_id)),
00137 vdbl::colflags(true));
00138 }
00139 gitable = (vdbl::standard_table*)
00140 get_database_ptr()->get_table("global info", get_dbuserid());
00141 if(gitable == NULL)
00142 {
00143 get_database_ptr()->create_table("global info", get_dbuserid());
00144 gitable = (vdbl::standard_table*)
00145 get_database_ptr()->get_table("global info", get_dbuserid());
00146 if(gitable == NULL)
00147 throw api_exception(apiee_internal,
00148 "work_node::work_node: Database inconsistency (global info table)");
00149 gitable_id = get_database_ptr()->get_tableid("global info", get_dbuserid());
00150 }
00151 wnc = new work_node_context(this);
00152 __vdb = new vdbl::viewdbase(*this->database()->get_local_copy(),
00153 this->get_dbuserid(), *wnc,
00154 std::vector<std::pair<vdbl::tableid,vdbl::rowid> >(
00155 this->get_annotations().begin(),
00156 this->get_annotations().end()));
00157 make_node_ranges(false);
00158 make_node_order();
00159 init_cnumbers();
00160 }
00161
00162 work_node::work_node(const search_node_id& _i, const vdbl::userid& _dui,
00163 gptr<model>& __m, gptr<vdbl::database>& __d,
00164 const std::vector<annotation>& __an,
00165 const std::list<delta_id>& __de, gptr<search_node>* _gm,
00166 search_node_relation snr, vdbl::viewdbase* vdbf) :
00167 _Base(_i, _dui, __m, _gm, __d, __an, snr),
00168 deltas(__de),
00169
00170 deltanew_it(deltas.end()),
00171
00172 parents_in_graph(),
00173 undeltas(),
00174 __vdbf(vdbf),
00175 node_ranges(),
00176 node_order(),
00177 infeasible(false),
00178 gain_factor(1.),
00179 globalinfo(),
00180 _tnum(0),
00181 proposed_splits(),
00182 split_delta_ids(),
00183 n_bds(0),
00184 n_lin(0),
00185 n_quad(0),
00186 n_poly(0),
00187 n_other(0)
00188 {
00189 init_all();
00190 }
00191
00192 work_node::work_node(const full_node& _f, const std::list<delta_id>& __de,
00193 vdbl::viewdbase* vdbf) :
00194 _Base(_f),
00195 deltas(__de),
00196
00197 deltanew_it(deltas.end()),
00198
00199 parents_in_graph(),
00200 undeltas(),
00201 __vdbf(vdbf),
00202 node_ranges(),
00203 node_order(),
00204 infeasible(false),
00205 gain_factor(1.),
00206 globalinfo(),
00207 _tnum(0),
00208 proposed_splits(),
00209 split_delta_ids(),
00210 n_bds(0),
00211 n_lin(0),
00212 n_quad(0),
00213 n_poly(0),
00214 n_other(0)
00215 {
00216 init_all();
00217 set_rowid(_f.get_rowid());
00218 }
00219
00220 void work_node::init_cnumbers()
00221 {
00222 expression_walker _c;
00223 int h = (**_m).constraints.size();
00224 n_bds = n_lin = n_quad = n_poly = n_other = 0;
00225 for(int i = 0; i < h; ++i)
00226 {
00227 _c = (**_m).constraints[i];
00228 if(_c->is(ex_bound))
00229 n_bds++;
00230 else if(_c->is(ex_linear))
00231 n_lin++;
00232 else if(_c->is(ex_quadratic))
00233 n_quad++;
00234 else if(_c->is(ex_polynomial))
00235 n_poly++;
00236 else
00237 n_other++;
00238 }
00239 log_vol = compute_log_volume(node_ranges);
00240 }
00241
00242 void work_node::make_node_ranges(bool keep_old_ranges)
00243 {
00244 unsigned int n = (**_m).number_of_nodes();
00245 if(n > node_ranges.size())
00246 {
00247 node_ranges.reserve(n);
00248 node_ranges.insert(node_ranges.end(), n-node_ranges.size(),
00249 interval(-COCO_INF,COCO_INF));
00250 }
00251 for(unsigned int i = 0; i < n; ++i)
00252 {
00253 if((**_m).node(i) != (**_m).ground())
00254 {
00255 if(!keep_old_ranges || node_ranges[i].is_entire())
00256 node_ranges[i] = (**_m).node(i)->f_bounds;
00257 }
00258 else
00259 node_ranges[i] = interval(-COCO_INF,COCO_INF);
00260 }
00261 }
00262
00263 void work_node::make_node_order()
00264 {
00265 graphorder(**_m, node_order);
00266 }
00267
00268 #define MAX_VOL_COMP 1.e12
00269 #define MIN_VOL_WIDTH DBL_MIN
00270
00271 double work_node::compute_log_volume(const std::vector<interval>& _r) const
00272 {
00273
00274
00275
00276 unsigned int n = (**_m).number_of_variables();
00277 double lv(0);
00278 double help;
00279
00280 for(unsigned int i = 0; i < n; ++i)
00281 {
00282 if((**_m).var(i)->sem.kj_flag())
00283 continue;
00284 const interval& nds(_r[(**_m).var(i)->node_num]);
00285 if(nds.is_bounded())
00286 {
00287 help = nds.width();
00288 if(help < MIN_VOL_WIDTH)
00289 lv -= MAX_VOL_COMP;
00290 else
00291 lv += std::log(help);
00292 }
00293 else
00294 lv += MAX_VOL_COMP;
00295 }
00296 return lv;
00297 }
00298
00299 void work_node::set_globalinfo()
00300 {
00301 if(gitable == NULL)
00302 throw api_exception(apiee_internal,
00303 "work_node::work_node: Database inconsistency (global info table)");
00304 vdbl::table::row_const_iterator r0i(gitable->row_begin());
00305 if(r0i != gitable->row_end())
00306 {
00307 bool error(false);
00308 vdbl::table::col_const_iterator ci, ce(gitable->col_end());
00309 for(ci = gitable->col_begin(); ci != ce; ++ci)
00310 {
00311 basic_alltype *bat;
00312 error = !gitable->retrieve(*r0i, (*ci).second, wnc, bat);
00313 if(error)
00314 throw api_exception(apiee_internal,
00315 "work_node::work_node: Database inconsistency (global info table)/get col");
00316 error = !globalinfo.sinsert((*ci).first, *bat, true);
00317 if(error)
00318 throw api_exception(apiee_internal,
00319 "work_node::work_node: Database inconsistency (global info table)/update cache");
00320 }
00321 }
00322 }
00323
00324
00325 bool work_node::global_info(basic_alltype& b, const std::string& i) const
00326 {
00327 b = globalinfo.sfind(i);
00328 if(b.empty())
00329 return globalinfo.defd(i);
00330 return true;
00331 }
00332
00333 basic_alltype work_node::global_info(const std::string& i) const
00334 {
00335 return globalinfo.sfind(i);
00336 }
00337
00338 }