00001 #include "vsrl_dynamic_program.h"
00002 #include <vcl_cstdlib.h>
00003 #include <vsrl/vsrl_token.h>
00004 #include <vsrl/vsrl_null_token.h>
00005 #include <vsrl/vsrl_parameters.h>
00006 #include <vcl_cassert.h>
00007 #include <vcl_iostream.h>
00008
00009
00010
00011
00012 vsrl_dynamic_program::vsrl_dynamic_program()
00013 {
00014
00015
00016 search_range_= vsrl_parameters::instance()->correlation_range;
00017 inner_cost_= vsrl_parameters::instance()->inner_cost;
00018 outer_cost_= vsrl_parameters::instance()->outer_cost;
00019 continuity_cost_= vsrl_parameters::instance()->continuity_cost;
00020 num_row_=0;
00021 num_col_=0;
00022
00023 inner_null_token_ = new vsrl_null_token();
00024 outer_null_token_ = new vsrl_null_token();
00025 inner_null_token_->set_cost(inner_cost_);
00026 outer_null_token_->set_cost(outer_cost_);
00027
00028 cost_matrix_=0;
00029 }
00030
00031
00032 vsrl_dynamic_program::~vsrl_dynamic_program()
00033 {
00034 delete inner_null_token_;
00035 delete outer_null_token_;
00036
00037
00038
00039 deallocate_cost_matrix();
00040 }
00041
00042 void vsrl_dynamic_program::set_tokens(token_list &l1,
00043 token_list &l2)
00044 {
00045
00046 if (l1.empty() || l2.empty())
00047 {
00048 vcl_cout << "warning empty list\n";
00049 return;
00050 }
00051
00052
00053 list1_.clear();
00054 token_list::iterator ti;
00055
00056 for (ti=l1.begin();ti!=l1.end();ti++)
00057 {
00058 list1_.push_back(*ti);
00059 }
00060
00061
00062
00063
00064 list2_.clear();
00065
00066
00067 list2_.push_back(outer_null_token_);
00068 for (ti=l2.begin();ti!=l2.end();ti++)
00069 {
00070
00071 list2_.push_back(*ti);
00072
00073 list2_.push_back(inner_null_token_);
00074 }
00075
00076
00077 list2_[list2_.size()-1]=outer_null_token_;
00078
00079
00080 num_row_= list1_.size();
00081 num_col_= list2_.size();
00082
00083
00084
00085
00086 }
00087
00088
00089
00090 void vsrl_dynamic_program::define_search_range()
00091 {
00092 for (unsigned int i=0;i<list1_.size();i++)
00093 {
00094 int low=i*2+1 - 2*search_range_;
00095 int high=i*2+1 + 2*search_range_;
00096
00097 if (low<0)
00098 low=0;
00099 if ((unsigned int)low>=list2_.size())
00100 low=list2_.size()-1;
00101 if (high<0)
00102 high=0;
00103 if ((unsigned int)high>list2_.size())
00104 high=list2_.size();
00105
00106 lower_search_range_.push_back(low);
00107 upper_search_range_.push_back(high);
00108 }
00109 }
00110
00111 void vsrl_dynamic_program::define_search_range(vnl_vector<int > curr_row)
00112 {
00113 for (unsigned int i=0;i<list1_.size();i++)
00114 {
00115 int low=curr_row[i]*2+1 - 2*search_range_;
00116 int high=curr_row[i]*2+1 + 2*search_range_;
00117
00118 if (low<0)
00119 low=0;
00120 if ((unsigned int)low>=list2_.size())
00121 low=list2_.size()-1;
00122 if (high<0)
00123 high=0;
00124 if ((unsigned int)high>list2_.size())
00125 high=list2_.size();
00126
00127 lower_search_range_.push_back(low);
00128 upper_search_range_.push_back(high);
00129 }
00130 }
00131
00132
00133
00134 void vsrl_dynamic_program::set_inner_cost(double cost)
00135 {
00136 inner_cost_ = cost;
00137 inner_null_token_->set_cost(cost);
00138 }
00139
00140
00141 void vsrl_dynamic_program::set_outer_cost(double cost)
00142 {
00143 outer_cost_ = cost;
00144 outer_null_token_->set_cost(cost);
00145 }
00146
00147
00148
00149 void vsrl_dynamic_program::set_continuity_cost(double cost)
00150 {
00151 continuity_cost_ = cost;
00152 }
00153
00154
00155 void vsrl_dynamic_program::set_search_range(int range)
00156 {
00157 search_range_ = range;
00158 }
00159
00160
00161
00162 bool vsrl_dynamic_program::allocate_cost_matrix()
00163 {
00164
00165
00166
00167 if (!num_row_ || !num_col_)
00168 {
00169 vcl_cout << "must set new token lists\n";
00170 cost_matrix_ = 0;
00171 return false;
00172 }
00173
00174 cost_matrix_ = (assignment_node**)(vcl_malloc(num_row_ * sizeof(*cost_matrix_)));
00175
00176 for (int i=0;i<num_row_;i++)
00177 cost_matrix_[i]=(assignment_node*)(vcl_malloc(num_col_ * sizeof(**cost_matrix_)));
00178
00179
00180
00181 for (int i=0;i<num_row_;i++)
00182 for (int j=0;j<num_col_;j++)
00183 {
00184 cost_matrix_[i][j].index1=i;
00185 cost_matrix_[i][j].index2=j;
00186 cost_matrix_[i][j].prior_index1=0;
00187 cost_matrix_[i][j].prior_index2=0;
00188 cost_matrix_[i][j].cost=1000000;
00189 cost_matrix_[i][j].num_null1=0;
00190 }
00191 return true;
00192 }
00193
00194 void vsrl_dynamic_program::deallocate_cost_matrix()
00195 {
00196
00197
00198 for (int i=0;i<num_row_;i++)
00199 vcl_free((char*)(cost_matrix_[i]));
00200
00201 vcl_free((char*)cost_matrix_);
00202
00203 cost_matrix_=0;
00204 num_row_=0;
00205 num_col_=0;
00206 }
00207
00208 double vsrl_dynamic_program::execute()
00209 {
00210
00211
00212
00213
00214 if (!allocate_cost_matrix())
00215 return 0.0;
00216
00217
00218
00219
00220
00221 for (int i=0;i<num_row_;i++)
00222 for (int j=lower_search_range_[i];j<upper_search_range_[i];j++)
00223 compute_cost(i,j);
00224 #ifdef DEBUG
00225 for (int i=0;i<num_row_;i++)
00226 {
00227 vcl_cout<<'\n';
00228 for (int j=lower_search_range_[i];j<upper_search_range_[i];j++)
00229 vcl_cout<<cost_matrix_[i][j].cost<<' ';
00230 }
00231 #endif
00232
00233
00234 double cost= optimum_assignment();
00235
00236
00237
00238 return cost;
00239 }
00240
00241 void vsrl_dynamic_program::compute_cost(int i, int j)
00242 {
00243
00244
00245
00246 vsrl_token *tok1 = list1_[i];
00247 vsrl_token *tok2 = list2_[j];
00248
00249
00250
00251
00252 double direct_cost = tok1->cost(tok2);
00253
00254
00255
00256 if (i==0)
00257 {
00258
00259
00260
00261 for (int k=0;k<j;k++)
00262 {
00263 if (!list2_[k]->null_token())
00264 {
00265
00266
00267 direct_cost = direct_cost + outer_cost_;
00268 }
00269 }
00270 }
00271
00272
00273
00274 if (i+1==int(list1_.size()))
00275 {
00276
00277
00278
00279
00280 for (unsigned int k=j+1;k<list2_.size();k++)
00281 {
00282 if (!list2_[k]->null_token())
00283 {
00284
00285
00286 direct_cost = direct_cost + outer_cost_;
00287 }
00288 }
00289 }
00290
00291
00292
00293 double new_num_null1 = 0;
00294 double prior_cost = 0;
00295
00296 int p_i =i-1;
00297 int p_j =0;
00298
00299 if (i>0)
00300 {
00301
00302
00303
00304
00305
00306 int upper_j = j;
00307 if (tok2->null_token())
00308 {
00309
00310
00311
00312
00313 upper_j++;
00314 }
00315
00316
00317 prior_cost = 100000;
00318
00319
00320
00321 double num_null1;
00322
00323
00324
00325 for (int k=lower_search_range_[p_i];k<upper_j;k++)
00326 {
00327
00328
00329 double cost = cost_matrix_[p_i][k].cost;
00330
00331
00332
00333
00334 cost = cost + tok1->incremental_cost(tok2,list1_[p_i],list2_[k]);
00335
00336
00337
00338
00339 if (j==k)
00340 {
00341
00342
00343
00344
00345 num_null1=cost_matrix_[p_i][k].num_null1 + 1;
00346 }
00347 else
00348 {
00349
00350
00351
00352 if (list2_[j]->null_token())
00353 {
00354
00355 num_null1=1;
00356 }
00357 else
00358 {
00359
00360 num_null1=0;
00361 }
00362 }
00363
00364
00365
00366
00367
00368
00369 cost = cost + num_null1 * continuity_cost_;
00370
00371
00372
00373
00374
00375
00376
00377 double num_null2=0;
00378
00379 for (int l=k+1;l<j;l++)
00380 {
00381 if (!list2_[l]->null_token())
00382 {
00383
00384
00385 cost = cost + inner_cost_;
00386 num_null2++;
00387 cost=cost+num_null2 * continuity_cost_;
00388 }
00389 }
00390
00391 if (cost<prior_cost)
00392 {
00393
00394 prior_cost = cost;
00395 p_j=k;
00396 new_num_null1=num_null1;
00397 }
00398 }
00399 }
00400
00401
00402
00403
00404 cost_matrix_[i][j].cost= direct_cost + prior_cost;
00405 cost_matrix_[i][j].num_null1 = new_num_null1;
00406
00407
00408
00409 cost_matrix_[i][j].prior_index1=p_i;
00410 cost_matrix_[i][j].prior_index2=p_j;
00411 }
00412
00413 double vsrl_dynamic_program::optimum_assignment()
00414 {
00415
00416
00417
00418
00419
00420
00421 token_list::iterator ti;
00422 for (ti=list1_.begin();ti!=list1_.end();ti++)
00423 (*ti)->set_assigned_token(0);
00424
00425 for (ti=list2_.begin();ti!=list2_.end();ti++)
00426 (*ti)->set_assigned_token(0);
00427
00428
00429 vsrl_token *tok1;
00430 vsrl_token *tok2;
00431
00432 int i = num_row_-1;
00433 int j=0;
00434 double min_cost=1000000;
00435
00436 for (int k=0;k<num_col_;k++)
00437 {
00438 if (cost_matrix_[i][k].cost < min_cost)
00439 {
00440 min_cost = cost_matrix_[i][k].cost;
00441 j=k;
00442 }
00443 }
00444
00445
00446
00447
00448 double total_cost=0;
00449
00450 while (i>=0)
00451 {
00452
00453 total_cost = total_cost + cost_matrix_[i][j].cost;
00454 tok1= list1_[i];
00455 tok2= list2_[j];
00456
00457 if (!tok2->null_token())
00458 {
00459
00460 tok1->set_assigned_token(tok2);
00461 tok2->set_assigned_token(tok1);
00462 }
00463
00464
00465
00466 j=cost_matrix_[i][j].prior_index2;
00467
00468 i=i-1;
00469 }
00470
00471
00472
00473 return total_cost;
00474 }
00475
00476
00477
00478
00479 void vsrl_dynamic_program::print_direct_cost(int i, int j)
00480 {
00481
00482
00483 assert(i>=0);
00484 assert(j>=0);
00485 if ((unsigned int)i < list1_.size() && (unsigned int)j< list2_.size())
00486 {
00487 vsrl_token *tok1 = list1_[i];
00488 vsrl_token *tok2 = list2_[j];
00489
00490 double direct_cost = tok1->cost(tok2);
00491
00492 vcl_cout << "Direct cost " << i << " -> " << j << ' ' << direct_cost <<'\n';
00493 }
00494 }
00495
00496
00497 void vsrl_dynamic_program::print_cost(int i, int j)
00498 {
00499
00500
00501 assert(i>=0);
00502 assert(j>=0);
00503 if ((unsigned int)i < list1_.size() && (unsigned int)j< list2_.size())
00504 vcl_cout << "cost "<< i <<" -> "<< j <<' '<<cost_matrix_[i][j].cost <<'\n';
00505 }
00506
00507 void vsrl_dynamic_program::print_direct_costs(int i)
00508 {
00509
00510 vcl_cout << "Direct costs for token " << i << vcl_endl;
00511 for (int j=lower_search_range_[i];j<upper_search_range_[i];j++)
00512 print_direct_cost(i,j);
00513 }
00514
00515 void vsrl_dynamic_program::print_costs(int i)
00516 {
00517
00518 vcl_cout << "Printing the costs for token " << i << " in the range " << lower_search_range_[i]
00519 << " to " << upper_search_range_[i] << vcl_endl;
00520
00521 for (int j=lower_search_range_[i];j<upper_search_range_[i];j++)
00522 print_cost(i,j);
00523 }
00524
00525 void vsrl_dynamic_program::print_assignment_nodes(int i)
00526 {
00527 for (int j=lower_search_range_[i];j<upper_search_range_[i];j++)
00528 print_assignment_node(i,j);
00529 }
00530
00531
00532 void vsrl_dynamic_program::print_assignment_node(int i, int j)
00533 {
00534 vcl_cout << " assignment for node " << i << " -> " << j << vcl_endl
00535 << " prior assignment: " << cost_matrix_[i][j].prior_index1 << " -> "
00536 << cost_matrix_[i][j].prior_index2 << vcl_endl
00537 << " cost: " << cost_matrix_[i][j].cost << vcl_endl << vcl_endl;
00538 }
00539
00540 void vsrl_dynamic_program::print_assignment(int i)
00541 {
00542
00543
00544 vcl_cout << "Token " << i << " goes to ";
00545 vsrl_token *tok1 = (list1_[i]);
00546 vsrl_token *tok2 = tok1->get_assigned_token();
00547 if (tok2)
00548 vcl_cout << "token " << tok2->get_x() << vcl_endl;
00549 else
00550 vcl_cout << "the null token\n";
00551 }
00552
00553 void vsrl_dynamic_program::print_assignments()
00554 {
00555 for (unsigned int j=0;j<list1_.size();j++)
00556 print_assignment(j);
00557 }