GCoptimization.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. #include "GCoptimization.h"
  2. #include "LinkedBlockList.h"
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include <stdlib.h>
  6. using namespace OBJREC;
  7. // will leave this one just for the laughs :)
  8. //#define olga_assert(expr) assert(!(expr))
  9. /////////////////////////////////////////////////////////////////////////////////////////////////
  10. // First we have functions for the base class
  11. /////////////////////////////////////////////////////////////////////////////////////////////////
  12. // Constructor for base class
  13. GCoptimization::GCoptimization(SiteID nSites, LabelID nLabels)
  14. : m_datacostIndividual(0)
  15. , m_smoothcostIndividual(0)
  16. , m_smoothcostFn(0)
  17. , m_datacostFn(0)
  18. , m_set_up_t_links_swap(0)
  19. , m_set_up_t_links_expansion(0)
  20. , m_set_up_n_links_swap(0)
  21. , m_set_up_n_links_expansion(0)
  22. , m_giveSmoothEnergyInternal(0)
  23. , m_giveDataEnergyInternal(0)
  24. , m_datacostFnDelete(0)
  25. , m_smoothcostFnDelete(0)
  26. , m_random_label_order(false)
  27. {
  28. assert( nLabels > 1 && nSites > 0);
  29. m_num_labels = nLabels;
  30. m_num_sites = nSites;
  31. m_lookupSiteVar = (SiteID *) new SiteID[m_num_sites];
  32. m_labelTable = (LabelID *) new LabelID[m_num_labels];
  33. m_labeling = (LabelID *) new LabelID[m_num_sites];
  34. if ( !m_lookupSiteVar || !m_labelTable || !m_labeling) {
  35. if (m_lookupSiteVar) delete [] m_lookupSiteVar;
  36. if (m_labelTable) delete [] m_labelTable;
  37. if (m_labeling) delete [] m_labeling;
  38. handleError("Not enough memory");
  39. }
  40. for ( LabelID i = 0; i < m_num_labels; i++ )
  41. m_labelTable[i] = i;
  42. for ( SiteID i = 0; i < m_num_sites; i++ ) {
  43. m_labeling[i] = (LabelID) 0;
  44. m_lookupSiteVar[i] = (SiteID) - 1;
  45. }
  46. srand((unsigned int) time(NULL));
  47. }
  48. //-------------------------------------------------------------------
  49. GCoptimization::~GCoptimization()
  50. {
  51. delete [] m_labelTable;
  52. delete [] m_lookupSiteVar;
  53. delete [] m_labeling;
  54. if (m_datacostFnDelete) m_datacostFnDelete(m_datacostFn);
  55. if (m_smoothcostFnDelete) m_smoothcostFnDelete(m_smoothcostFn);
  56. if (m_datacostIndividual) delete [] m_datacostIndividual;
  57. if (m_smoothcostIndividual) delete [] m_smoothcostIndividual;
  58. }
  59. //------------------------------------------------------------------
  60. void GCoptimization::setDataCost(DataCostFn fn) {
  61. specializeDataCostFunctor(DataCostFnFromFunction(fn));
  62. }
  63. //------------------------------------------------------------------
  64. void GCoptimization::setDataCost(DataCostFnExtra fn, void *extraData) {
  65. specializeDataCostFunctor(DataCostFnFromFunctionExtra(fn, extraData));
  66. }
  67. //-------------------------------------------------------------------
  68. void GCoptimization::setDataCost(EnergyTermType *dataArray) {
  69. specializeDataCostFunctor(DataCostFnFromArray(dataArray, m_num_labels));
  70. }
  71. //-------------------------------------------------------------------
  72. void GCoptimization::setDataCost(SiteID s, LabelID l, EnergyTermType e) {
  73. if (!m_datacostIndividual) {
  74. if ( m_datacostFn ) handleError("Data Costs are already initialized");
  75. m_datacostIndividual = new EnergyTermType[m_num_sites*m_num_labels];
  76. memset(m_datacostIndividual, 0, m_num_sites*m_num_labels*sizeof(EnergyTermType));
  77. specializeDataCostFunctor(DataCostFnFromArray(m_datacostIndividual, m_num_labels));
  78. }
  79. m_datacostIndividual[s*m_num_labels + l] = e;
  80. }
  81. //-------------------------------------------------------------------
  82. void GCoptimization::setDataCostFunctor(DataCostFunctor* f) {
  83. if ( m_datacostFn ) handleError("Data Costs are already initialized");
  84. m_datacostFn = f;
  85. m_giveDataEnergyInternal = &GCoptimization::giveDataEnergyInternal<DataCostFunctor>;
  86. m_set_up_t_links_expansion = &GCoptimization::set_up_t_links_expansion<DataCostFunctor>;
  87. m_set_up_t_links_swap = &GCoptimization::set_up_t_links_swap<DataCostFunctor>;
  88. }
  89. //-------------------------------------------------------------------
  90. void GCoptimization::setSmoothCost(SmoothCostFn fn) {
  91. specializeSmoothCostFunctor(SmoothCostFnFromFunction(fn));
  92. }
  93. //-------------------------------------------------------------------
  94. void GCoptimization::setSmoothCost(SmoothCostFnExtra fn, void* extraData) {
  95. specializeSmoothCostFunctor(SmoothCostFnFromFunctionExtra(fn, extraData));
  96. }
  97. //-------------------------------------------------------------------
  98. void GCoptimization::setSmoothCost(EnergyTermType *smoothArray) {
  99. specializeSmoothCostFunctor(SmoothCostFnFromArray(smoothArray, m_num_labels));
  100. }
  101. //-------------------------------------------------------------------
  102. void GCoptimization::setSmoothCost(LabelID l1, GCoptimization::LabelID l2, EnergyTermType e) {
  103. if (!m_smoothcostIndividual) {
  104. if ( m_smoothcostFn ) handleError("Smoothness Costs are already initialized");
  105. m_smoothcostIndividual = new EnergyTermType[m_num_labels*m_num_labels];
  106. memset(m_smoothcostIndividual, 0, m_num_labels*m_num_labels*sizeof(EnergyTermType));
  107. specializeSmoothCostFunctor(SmoothCostFnFromArray(m_smoothcostIndividual, m_num_labels));
  108. }
  109. m_smoothcostIndividual[l1*m_num_labels + l2] = e;
  110. }
  111. //-------------------------------------------------------------------
  112. void GCoptimization::setSmoothCostFunctor(SmoothCostFunctor* f) {
  113. if ( m_smoothcostFn ) handleError("Smoothness Costs are already initialized");
  114. m_smoothcostFn = f;
  115. m_giveSmoothEnergyInternal = &GCoptimization::giveSmoothEnergyInternal<SmoothCostFunctor>;
  116. m_set_up_n_links_expansion = &GCoptimization::set_up_n_links_expansion<SmoothCostFunctor>;
  117. m_set_up_n_links_swap = &GCoptimization::set_up_n_links_swap<SmoothCostFunctor>;
  118. }
  119. //-------------------------------------------------------------------
  120. GCoptimization::EnergyType GCoptimization::giveSmoothEnergy()
  121. {
  122. if (readyToOptimise())
  123. return( (this->*m_giveSmoothEnergyInternal)() );
  124. else {
  125. handleError("Not ready to optimize yet. Set up data and smooth costs first");
  126. return(0);
  127. }
  128. }
  129. //-------------------------------------------------------------------
  130. GCoptimization::EnergyType GCoptimization::giveDataEnergy()
  131. {
  132. if (readyToOptimise())
  133. return( (this->*m_giveDataEnergyInternal)() );
  134. else {
  135. handleError("Not ready to optimize yet. Set up data and smooth costs first");
  136. return(0);
  137. }
  138. }
  139. //-------------------------------------------------------------------
  140. GCoptimization::EnergyType GCoptimization::compute_energy()
  141. {
  142. if (readyToOptimise())
  143. return( (this->*m_giveDataEnergyInternal)() + (this->*m_giveSmoothEnergyInternal)());
  144. else {
  145. handleError("Not ready to optimize yet. Set up data and smooth costs first");
  146. return(0);
  147. }
  148. }
  149. //-------------------------------------------------------------------
  150. void GCoptimization::scramble_label_table()
  151. {
  152. LabelID r1, r2, temp;
  153. LabelID num_times, cnt;
  154. num_times = m_num_labels;
  155. for ( cnt = 0; cnt < num_times; cnt++ )
  156. {
  157. r1 = rand() % m_num_labels;
  158. r2 = rand() % m_num_labels;
  159. temp = m_labelTable[r1];
  160. m_labelTable[r1] = m_labelTable[r2];
  161. m_labelTable[r2] = temp;
  162. }
  163. }
  164. //-------------------------------------------------------------------
  165. GCoptimization::EnergyType GCoptimization::expansion(int max_num_iterations )
  166. {
  167. int curr_cycle = 1;
  168. EnergyType new_energy, old_energy;
  169. new_energy = compute_energy();
  170. old_energy = new_energy + 1;
  171. while ( old_energy > new_energy && curr_cycle <= max_num_iterations)
  172. {
  173. old_energy = new_energy;
  174. new_energy = oneExpansionIteration();
  175. curr_cycle++;
  176. }
  177. return(new_energy);
  178. }
  179. //-------------------------------------------------------------------
  180. void GCoptimization::setLabelOrder(bool RANDOM_LABEL_ORDER)
  181. {
  182. m_random_label_order = RANDOM_LABEL_ORDER;
  183. }
  184. //-------------------------------------------------------------------
  185. bool GCoptimization::readyToOptimise()
  186. {
  187. if (!m_smoothcostFn)
  188. {
  189. handleError("Smoothness term is not set up yet!");
  190. return(false);
  191. }
  192. if (!m_datacostFn)
  193. {
  194. handleError("Data term is not set up yet!");
  195. return(false);
  196. }
  197. return(true);
  198. }
  199. //------------------------------------------------------------------
  200. void GCoptimization::handleError(const char *message)
  201. {
  202. throw GCException(message);
  203. }
  204. //-------------------------------------------------------------------//
  205. // METHODS for EXPANSION MOVES //
  206. //-------------------------------------------------------------------//
  207. void GCoptimization::set_up_expansion_energy(SiteID size, LabelID alpha_label, Energy *e,
  208. VarID *variables, SiteID *activeSites )
  209. {
  210. (this->*m_set_up_t_links_expansion)(size, alpha_label, e, variables, activeSites);
  211. (this->*m_set_up_n_links_expansion)(size, alpha_label, e, variables, activeSites);
  212. }
  213. //-------------------------------------------------------------------
  214. // Sets up the energy and optimizes it. Also updates labels of sites, if needed. ActiveSites
  215. // are the sites participating in expansion. They are not labeled alpha currrently
  216. void GCoptimization::solveExpansion(SiteID size, SiteID *activeSites, LabelID alpha_label)
  217. {
  218. SiteID i, site;
  219. if ( !readyToOptimise() ) handleError("Set up data and smoothness terms first. ");
  220. if ( size == 0 ) return;
  221. Energy *e = new Energy();
  222. Energy::Var *variables = (Energy::Var *) new Energy::Var[size];
  223. for ( i = 0; i < size; i++ )
  224. variables[i] = e ->add_variable();
  225. set_up_expansion_energy(size, alpha_label, e, variables, activeSites);
  226. Energy::TotalValue Emin = e -> minimize();
  227. for ( i = 0; i < size; i++ )
  228. {
  229. site = activeSites[i];
  230. if ( m_labeling[site] != alpha_label )
  231. {
  232. if ( e->get_var(variables[i]) == 0 )
  233. {
  234. m_labeling[site] = alpha_label;
  235. }
  236. }
  237. m_lookupSiteVar[site] = -1;
  238. }
  239. delete [] variables;
  240. delete e;
  241. }
  242. //-------------------------------------------------------------------
  243. // alpha expansion on all sites not currently labeled alpha
  244. void GCoptimization::alpha_expansion(LabelID alpha_label)
  245. {
  246. SiteID i = 0, size = 0;
  247. assert( alpha_label >= 0 && alpha_label < m_num_labels);
  248. SiteID *activeSites = new SiteID[m_num_sites];
  249. for ( i = 0; i < m_num_sites; i++ )
  250. {
  251. if ( m_labeling[i] != alpha_label )
  252. {
  253. activeSites[size] = i;
  254. m_lookupSiteVar[i] = size;
  255. size++;
  256. }
  257. }
  258. solveExpansion(size, activeSites, alpha_label);
  259. delete [] activeSites;
  260. }
  261. //-------------------------------------------------------------------
  262. // alpha expansion on subset of sites in array *sites
  263. void GCoptimization::alpha_expansion(LabelID alpha_label, SiteID *sites, SiteID num )
  264. {
  265. SiteID i, size = 0;
  266. SiteID *activeSites = new SiteID[num];
  267. for ( i = 0; i < num; i++ )
  268. {
  269. if ( m_labeling[sites[i]] != alpha_label )
  270. {
  271. m_lookupSiteVar[sites[i]] = size;
  272. activeSites[size] = sites[i];
  273. size++;
  274. }
  275. }
  276. solveExpansion(size, activeSites, alpha_label);
  277. delete [] activeSites;
  278. }
  279. //-------------------------------------------------------------------
  280. GCoptimization::EnergyType GCoptimization::oneExpansionIteration()
  281. {
  282. LabelID next;
  283. if (m_random_label_order) scramble_label_table();
  284. for (next = 0; next < m_num_labels; next++ )
  285. {
  286. alpha_expansion(m_labelTable[next]);
  287. }
  288. return(compute_energy());
  289. }
  290. //-------------------------------------------------------------------//
  291. // METHODS for SWAP MOVES //
  292. //-------------------------------------------------------------------//
  293. GCoptimization::EnergyType GCoptimization::swap(int max_num_iterations )
  294. {
  295. int curr_cycle = 1;
  296. EnergyType new_energy, old_energy;
  297. new_energy = compute_energy();
  298. old_energy = new_energy + 1;
  299. while ( old_energy > new_energy && curr_cycle <= max_num_iterations)
  300. {
  301. old_energy = new_energy;
  302. new_energy = oneSwapIteration();
  303. curr_cycle++;
  304. }
  305. return(new_energy);
  306. }
  307. //--------------------------------------------------------------------------------
  308. GCoptimization::EnergyType GCoptimization::oneSwapIteration()
  309. {
  310. LabelID next, next1;
  311. if (m_random_label_order) scramble_label_table();
  312. for (next = 0; next < m_num_labels; next++ )
  313. for (next1 = m_num_labels - 1; next1 >= 0; next1-- )
  314. if ( m_labelTable[next] < m_labelTable[next1] )
  315. alpha_beta_swap(m_labelTable[next], m_labelTable[next1]);
  316. return(compute_energy());
  317. }
  318. //---------------------------------------------------------------------------------
  319. void GCoptimization::alpha_beta_swap(LabelID alpha_label, LabelID beta_label)
  320. {
  321. assert( alpha_label >= 0 && alpha_label < m_num_labels && beta_label >= 0 && beta_label < m_num_labels);
  322. SiteID i = 0, size = 0;
  323. SiteID *activeSites = new SiteID[m_num_sites];
  324. for ( i = 0; i < m_num_sites; i++ ) {
  325. if ( m_labeling[i] == alpha_label || m_labeling[i] == beta_label ) {
  326. activeSites[size] = i;
  327. m_lookupSiteVar[i] = size;
  328. size++;
  329. }
  330. }
  331. solveSwap(size, activeSites, alpha_label, beta_label);
  332. delete [] activeSites;
  333. }
  334. //-----------------------------------------------------------------------------------
  335. void GCoptimization::alpha_beta_swap(LabelID alpha_label, LabelID beta_label,
  336. SiteID *alphaSites, SiteID alpha_size, SiteID *betaSites,
  337. SiteID beta_size)
  338. {
  339. assert( !(alpha_label < 0 || alpha_label >= m_num_labels || beta_label < 0 || beta_label >= m_num_labels) );
  340. SiteID i, site, size = 0;
  341. SiteID *activeSites = new SiteID[alpha_size+beta_size];
  342. for ( i = 0; i < alpha_size; i++ )
  343. {
  344. site = alphaSites[i];
  345. assert(site >= 0 && site < m_num_sites );
  346. assert(m_labeling[site] == alpha_label);
  347. activeSites[size] = site;
  348. m_lookupSiteVar[site] = size;
  349. size++;
  350. }
  351. for ( i = 0; i < beta_size; i++ )
  352. {
  353. site = betaSites[i];
  354. assert(site >= 0 && site < m_num_sites );
  355. assert(m_labeling[site] == beta_label);
  356. activeSites[size] = site;
  357. m_lookupSiteVar[site] = size;
  358. size++;
  359. }
  360. solveSwap(size, activeSites, alpha_label, beta_label);
  361. delete [] activeSites;
  362. }
  363. //-----------------------------------------------------------------------------------
  364. void GCoptimization::solveSwap(SiteID size, SiteID *activeSites, LabelID alpha_label,
  365. LabelID beta_label)
  366. {
  367. SiteID i, site;
  368. if ( !readyToOptimise() ) handleError("Set up data and smoothness terms first. ");
  369. if ( size == 0 ) return;
  370. Energy *e = new Energy();
  371. Energy::Var *variables = (Energy::Var *) new Energy::Var[size];
  372. for ( i = 0; i < size; i++ )
  373. variables[i] = e ->add_variable();
  374. set_up_swap_energy(size, alpha_label, beta_label, e, variables, activeSites);
  375. Energy::TotalValue Emin = e -> minimize();
  376. for ( i = 0; i < size; i++ )
  377. {
  378. site = activeSites[i];
  379. if ( e->get_var(variables[i]) == 0 )
  380. m_labeling[site] = alpha_label;
  381. else m_labeling[site] = beta_label;
  382. m_lookupSiteVar[site] = -1;
  383. }
  384. delete [] variables;
  385. delete e;
  386. }
  387. //-----------------------------------------------------------------------------------
  388. void GCoptimization::set_up_swap_energy(SiteID size, LabelID alpha_label, LabelID beta_label,
  389. Energy* e, Energy::Var *variables, SiteID *activeSites)
  390. {
  391. (this->*m_set_up_t_links_swap)(size, alpha_label, beta_label, e, variables, activeSites);
  392. (this->*m_set_up_n_links_swap)(size, alpha_label, beta_label, e, variables, activeSites);
  393. }
  394. //////////////////////////////////////////////////////////////////////////////////////////////////
  395. // Functions for the GCoptimizationGridGraph, derived from GCoptimization
  396. ////////////////////////////////////////////////////////////////////////////////////////////////////
  397. GCoptimizationGridGraph::GCoptimizationGridGraph(SiteID width, SiteID height, LabelID num_labels)
  398. : GCoptimization(width*height, num_labels)
  399. {
  400. assert( (width > 1) && (height > 1) && (num_labels > 1 ));
  401. m_weightedGraph = 0;
  402. for (int i = 0; i < 4; i ++ ) m_unityWeights[i] = 1;
  403. m_width = width;
  404. m_height = height;
  405. m_numNeighbors = new SiteID[m_num_sites];
  406. m_neighbors = new SiteID[4*m_num_sites];
  407. SiteID indexes[4] = { -1, 1, -m_width, m_width};
  408. SiteID indexesL[3] = {1, -m_width, m_width};
  409. SiteID indexesR[3] = { -1, -m_width, m_width};
  410. SiteID indexesU[3] = {1, -1, m_width};
  411. SiteID indexesD[3] = {1, -1, -m_width};
  412. SiteID indexesUL[2] = {1, m_width};
  413. SiteID indexesUR[2] = { -1, m_width};
  414. SiteID indexesDL[2] = {1, -m_width};
  415. SiteID indexesDR[2] = { -1, -m_width};
  416. setupNeighbData(1, m_height - 1, 1, m_width - 1, 4, indexes);
  417. setupNeighbData(1, m_height - 1, 0, 1, 3, indexesL);
  418. setupNeighbData(1, m_height - 1, m_width - 1, m_width, 3, indexesR);
  419. setupNeighbData(0, 1, 1, width - 1, 3, indexesU);
  420. setupNeighbData(m_height - 1, m_height, 1, m_width - 1, 3, indexesD);
  421. setupNeighbData(0, 1, 0, 1, 2, indexesUL);
  422. setupNeighbData(0, 1, m_width - 1, m_width, 2, indexesUR);
  423. setupNeighbData(m_height - 1, m_height, 0, 1, 2, indexesDL);
  424. setupNeighbData(m_height - 1, m_height, m_width - 1, m_width, 2, indexesDR);
  425. }
  426. //-------------------------------------------------------------------
  427. GCoptimizationGridGraph::~GCoptimizationGridGraph()
  428. {
  429. delete [] m_numNeighbors;
  430. delete [] m_neighbors;
  431. if (m_weightedGraph) delete [] m_neighborsWeights;
  432. }
  433. //-------------------------------------------------------------------
  434. void GCoptimizationGridGraph::setupNeighbData(SiteID startY, SiteID endY, SiteID startX,
  435. SiteID endX, SiteID maxInd, SiteID *indexes)
  436. {
  437. SiteID x, y, pix;
  438. SiteID n;
  439. for ( y = startY; y < endY; y++ )
  440. for ( x = startX; x < endX; x++ )
  441. {
  442. pix = x + y * m_width;
  443. m_numNeighbors[pix] = maxInd;
  444. for (n = 0; n < maxInd; n++ )
  445. m_neighbors[pix*4+n] = pix + indexes[n];
  446. }
  447. }
  448. //-------------------------------------------------------------------
  449. bool GCoptimizationGridGraph::readyToOptimise()
  450. {
  451. GCoptimization::readyToOptimise();
  452. return(true);
  453. }
  454. //-------------------------------------------------------------------
  455. void GCoptimizationGridGraph::setSmoothCostVH(EnergyTermType *smoothArray, EnergyTermType *vCosts, EnergyTermType *hCosts)
  456. {
  457. setSmoothCost(smoothArray);
  458. m_weightedGraph = 1;
  459. computeNeighborWeights(vCosts, hCosts);
  460. }
  461. //-------------------------------------------------------------------
  462. void GCoptimizationGridGraph::giveNeighborInfo(SiteID site, SiteID *numSites, SiteID **neighbors, EnergyTermType **weights)
  463. {
  464. *numSites = m_numNeighbors[site];
  465. *neighbors = &m_neighbors[site*4];
  466. if (m_weightedGraph) *weights = &m_neighborsWeights[site*4];
  467. else *weights = m_unityWeights;
  468. }
  469. //-------------------------------------------------------------------
  470. void GCoptimizationGridGraph::computeNeighborWeights(EnergyTermType *vCosts, EnergyTermType *hCosts)
  471. {
  472. SiteID i, n, nSite;
  473. GCoptimization::EnergyTermType weight;
  474. m_neighborsWeights = new EnergyTermType[m_num_sites*4];
  475. for ( i = 0; i < m_num_sites; i++ )
  476. {
  477. for ( n = 0; n < m_numNeighbors[i]; n++ )
  478. {
  479. nSite = m_neighbors[4*i+n];
  480. if ( i - nSite == 1 ) weight = hCosts[nSite];
  481. else if (i - nSite == -1 ) weight = hCosts[i];
  482. else if ( i - nSite == m_width ) weight = vCosts[nSite];
  483. else if (i - nSite == -m_width ) weight = vCosts[i];
  484. m_neighborsWeights[i*4+n] = weight;
  485. }
  486. }
  487. }
  488. ////////////////////////////////////////////////////////////////////////////////////////////////
  489. // Functions for the GCoptimizationGeneralGraph, derived from GCoptimization
  490. ////////////////////////////////////////////////////////////////////////////////////////////////////
  491. GCoptimizationGeneralGraph::GCoptimizationGeneralGraph(SiteID num_sites, LabelID num_labels): GCoptimization(num_sites, num_labels)
  492. {
  493. assert( num_sites > 1 && num_labels > 1 );
  494. m_neighborsIndexes = 0;
  495. m_neighborsWeights = 0;
  496. m_numNeighbors = 0;
  497. m_neighbors = 0;
  498. m_needTodeleteNeighbors = true;
  499. m_needToFinishSettingNeighbors = true;
  500. }
  501. //------------------------------------------------------------------
  502. GCoptimizationGeneralGraph::~GCoptimizationGeneralGraph()
  503. {
  504. if ( m_neighbors ) {
  505. delete [] m_neighbors;
  506. }
  507. if ( m_numNeighbors && m_needTodeleteNeighbors )
  508. {
  509. for ( SiteID i = 0; i < m_num_sites; i++ )
  510. {
  511. if (m_numNeighbors[i] != 0 )
  512. {
  513. delete [] m_neighborsIndexes[i];
  514. delete [] m_neighborsWeights[i];
  515. }
  516. }
  517. delete [] m_numNeighbors;
  518. delete [] m_neighborsIndexes;
  519. delete [] m_neighborsWeights;
  520. }
  521. }
  522. //-------------------------------------------------------------------
  523. bool GCoptimizationGeneralGraph::readyToOptimise()
  524. {
  525. GCoptimization::readyToOptimise();
  526. if (m_needToFinishSettingNeighbors) finishSettingNeighbors();
  527. return(true);
  528. }
  529. //------------------------------------------------------------------
  530. void GCoptimizationGeneralGraph::finishSettingNeighbors()
  531. {
  532. Neighbor *tmp;
  533. SiteID i, site, count;
  534. m_needToFinishSettingNeighbors = false;
  535. EnergyTermType *tempWeights = new EnergyTermType[m_num_sites];
  536. SiteID *tempIndexes = new SiteID[m_num_sites];
  537. if ( !tempWeights || !tempIndexes ) handleError("Not enough memory");
  538. m_numNeighbors = new SiteID[m_num_sites];
  539. m_neighborsIndexes = new SiteID*[m_num_sites];
  540. m_neighborsWeights = new EnergyTermType*[m_num_sites];
  541. if ( !m_numNeighbors || !m_neighborsIndexes || !m_neighborsWeights ) handleError("Not enough memory");
  542. for ( site = 0; site < m_num_sites; site++ )
  543. {
  544. if ( !m_neighbors[site].isEmpty() )
  545. {
  546. m_neighbors[site].setCursorFront();
  547. count = 0;
  548. while ( m_neighbors[site].hasNext() )
  549. {
  550. tmp = (Neighbor *) (m_neighbors[site].next());
  551. tempIndexes[count] = tmp->to_node;
  552. tempWeights[count] = tmp->weight;
  553. delete tmp;
  554. count++;
  555. }
  556. m_numNeighbors[site] = count;
  557. m_neighborsIndexes[site] = new SiteID[count];
  558. m_neighborsWeights[site] = new EnergyTermType[count];
  559. if ( !m_neighborsIndexes[site] || !m_neighborsWeights[site] ) handleError("Not enough memory");
  560. for ( i = 0; i < count; i++ )
  561. {
  562. m_neighborsIndexes[site][i] = tempIndexes[i];
  563. m_neighborsWeights[site][i] = tempWeights[i];
  564. }
  565. }
  566. else m_numNeighbors[site] = 0;
  567. }
  568. delete [] tempIndexes;
  569. delete [] tempWeights;
  570. delete [] m_neighbors;
  571. m_neighbors = (LinkedBlockList *) new LinkedBlockList[1];
  572. // this signals that the neibhorhood system is set, in case user calls setAllNeighbors
  573. }
  574. //------------------------------------------------------------------------------
  575. void GCoptimizationGeneralGraph::giveNeighborInfo(SiteID site, SiteID *numSites,
  576. SiteID **neighbors, EnergyTermType **weights)
  577. {
  578. (*numSites) = m_numNeighbors[site];
  579. (*neighbors) = m_neighborsIndexes[site];
  580. (*weights) = m_neighborsWeights[site];
  581. }
  582. //------------------------------------------------------------------
  583. void GCoptimizationGeneralGraph::setNeighbors(SiteID site1, SiteID site2, EnergyTermType weight)
  584. {
  585. assert( site1 < m_num_sites && site1 >= 0 && site2 < m_num_sites && site2 >= 0);
  586. if ( m_needToFinishSettingNeighbors == false ) handleError("Already set up neighborhood system");
  587. if ( !m_neighbors )
  588. {
  589. m_neighbors = (LinkedBlockList *) new LinkedBlockList[m_num_sites];
  590. if ( !m_neighbors ) handleError("Not enough memory");
  591. }
  592. Neighbor *temp1 = (Neighbor *) new Neighbor;
  593. Neighbor *temp2 = (Neighbor *) new Neighbor;
  594. temp1->weight = weight;
  595. temp1->to_node = site2;
  596. temp2->weight = weight;
  597. temp2->to_node = site1;
  598. m_neighbors[site1].addFront(temp1);
  599. m_neighbors[site2].addFront(temp2);
  600. }
  601. //------------------------------------------------------------------
  602. void GCoptimizationGeneralGraph::setAllNeighbors(SiteID *numNeighbors, SiteID **neighborsIndexes,
  603. EnergyTermType **neighborsWeights)
  604. {
  605. m_needTodeleteNeighbors = false;
  606. m_needToFinishSettingNeighbors = false;
  607. if ( m_neighbors ) handleError("Already set up neighborhood system");
  608. m_numNeighbors = numNeighbors;
  609. m_neighborsIndexes = neighborsIndexes;
  610. m_neighborsWeights = neighborsWeights;
  611. }