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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef _CMGRAPHS_MATCHDEC_H_
00037 #define _CMGRAPHS_MATCHDEC_H_
00038
00039
00040
00041 #include <vector>
00042 #include <algorithm>
00043 #include <new>
00044
00045
00046 #include "chomp/system/config.h"
00047 #include "chomp/system/textfile.h"
00048 #include "chomp/struct/digraph.h"
00049 #include "chomp/struct/flatmatr.h"
00050
00051
00052 #include "config.h"
00053 #include "typedefs.h"
00054 #include "matcharr.h"
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 template <class typeCubes>
00065 inline bool intersect (const typeCubes &X, const typeCubes &Y)
00066 {
00067
00068 bool XY = (X. size () < Y. size ());
00069 const typeCubes &smaller = XY ? X : Y;
00070 const typeCubes &larger = XY? Y : X;
00071
00072
00073 int smallerSize = smaller. size ();
00074 for (int i = 0; i < smallerSize; ++ i)
00075 {
00076 if (larger. check (smaller [i]))
00077 return true;
00078 }
00079
00080 return false;
00081 }
00082
00083
00084
00085
00086
00087 template <class typeCubes>
00088 inline bool intersectSub (const typeCubes &fine, const typeCubes &coarse)
00089 {
00090 typedef typename typeCubes::value_type typeCube;
00091 typedef typename typeCube::CoordType typeCoord;
00092
00093
00094 int size = fine. size ();
00095 if (!size)
00096 return false;
00097
00098
00099 int dim = fine [0]. dim ();
00100 std::auto_ptr<typeCoord> coordPtr (new typeCoord [dim]);
00101 typeCoord *coord = coordPtr. get ();
00102
00103
00104
00105 for (int i = 0; i < size; ++ i)
00106 {
00107 fine [i]. coord (coord);
00108 for (int j = 0; j < dim; ++ j)
00109 coord [j] /= 2;
00110 if (coarse. check (typeCube (coord, dim)))
00111 return true;
00112 }
00113
00114 return false;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 inline bool matchMorseSets (const theMorseDecompositionType &morseDecM,
00126 const std::vector<int> &wrongIndM, const theCubMapType &theCubMap1M,
00127 std::vector<spcCubes> &refinedM,
00128 const theMorseDecompositionType &morseDecN,
00129 const std::vector<int> &wrongIndN, const theCubMapType &theCubMap1N,
00130 std::vector<spcCubes> &refinedN,
00131 bool matchOrdering)
00132 {
00133 using chomp::homology::sbug;
00134
00135
00136 int nSets = morseDecM. count ();
00137 if (nSets != morseDecN. count ())
00138 return false;
00139 if (!nSets)
00140 return true;
00141
00142
00143
00144 std::vector<std::vector<int> > MtoN (nSets);
00145 std::vector<std::vector<int> > NtoM (nSets);
00146 for (int m = 0; m < nSets; ++ m)
00147 {
00148 for (int n = 0; n < nSets; ++ n)
00149 {
00150 if (!intersect (morseDecM [m], morseDecN [n]))
00151 continue;
00152 MtoN [m]. push_back (n);
00153 NtoM [n]. push_back (m);
00154 }
00155 }
00156
00157
00158 bool bijection = true;
00159 for (int i = 0; i < nSets; ++ i)
00160 {
00161 if (MtoN [i]. empty () || NtoM [i]. empty ())
00162 return false;
00163 if ((MtoN [i]. size () > 1) || (NtoM [i]. size () > 1))
00164 bijection = false;
00165 }
00166
00167
00168 if (!bijection)
00169 {
00170
00171 sbug << "Note: No bijection in matching. Refining...\n";
00172
00173
00174 if (refinedM. empty ())
00175 refinedM. resize (nSets);
00176 if (refinedN. empty ())
00177 refinedN. resize (nSets);
00178
00179
00180
00181 std::vector<bool> refineM (nSets, false);
00182 std::vector<bool> refineN (nSets, false);
00183 for (int n = 0; n < nSets + nSets; ++ n)
00184 {
00185
00186 int index = (n < nSets) ? n : (n - nSets);
00187 std::vector<std::vector<int> > &AtoB =
00188 (n < nSets) ? MtoN : NtoM;
00189 if (AtoB [index]. size () <= 1)
00190 continue;
00191 std::vector<bool> &refineA =
00192 (n < nSets) ? refineM : refineN;
00193 std::vector<bool> &refineB =
00194 (n < nSets) ? refineN : refineM;
00195
00196
00197 refineA [index] = true;
00198 for (unsigned i = 0; i < AtoB [index]. size (); ++ i)
00199 refineB [AtoB [index] [i]] = true;
00200 }
00201
00202
00203 for (int n = 0; n < nSets + nSets; ++ n)
00204 {
00205
00206 int index = (n < nSets) ? n : (n - nSets);
00207 std::vector<bool> &refineA =
00208 (n < nSets) ? refineM : refineN;
00209 if (!refineA [index])
00210 continue;
00211 std::vector<spcCubes> &refinedA =
00212 (n < nSets) ? refinedM : refinedN;
00213 if (!refinedA [index]. empty ())
00214 continue;
00215 const theMorseDecompositionType &morseDecA =
00216 (n < nSets) ? morseDecM : morseDecN;
00217 if (morseDecA [index]. size () > maxRefineSize0)
00218 continue;
00219 const theCubMapType &theCubMap1 =
00220 (n < nSets) ? theCubMap1M : theCubMap1N;
00221 sbug << "- match subdiv " <<
00222 morseDecA [index]. size () << " -> ";
00223 subdivideCubes (morseDecA [index], refinedA [index]);
00224 sbug << refinedA [index]. size () << ". ";
00225 int result = invariantPart (refinedA [index],
00226 theCubMap1);
00227 if (result < 0)
00228 {
00229 spcCubes emptySet;
00230 refinedA [index] = emptySet;
00231 }
00232 }
00233
00234
00235 for (int n = 0; n < nSets + nSets; ++ n)
00236 {
00237
00238 int indA = (n < nSets) ? n : (n - nSets);
00239 std::vector<std::vector<int> > &AtoB =
00240 (n < nSets) ? MtoN : NtoM;
00241 if (AtoB. size () <= 1)
00242 continue;
00243 std::vector<std::vector<int> > &BtoA =
00244 (n < nSets) ? NtoM : MtoN;
00245 const theMorseDecompositionType &morseDecA =
00246 (n < nSets) ? morseDecM : morseDecN;
00247 const theMorseDecompositionType &morseDecB =
00248 (n < nSets) ? morseDecN : morseDecM;
00249 std::vector<spcCubes> &refinedA =
00250 (n < nSets) ? refinedM : refinedN;
00251 std::vector<spcCubes> &refinedB =
00252 (n < nSets) ? refinedN : refinedM;
00253
00254
00255 std::vector<int>::iterator begin =
00256 AtoB [indA]. begin ();
00257 for (unsigned i = 0; i < AtoB [indA]. size (); ++ i)
00258 {
00259
00260 int indB = AtoB [indA] [i];
00261
00262
00263 bool refA = !refinedA [indA]. empty ();
00264 bool refB = !refinedB [indB]. empty ();
00265
00266
00267 if (refA && refB && intersect
00268 (refinedA [indA], refinedB [indB]))
00269 {
00270 continue;
00271 }
00272 else if (refA && !refB && intersectSub
00273 (refinedA [indA], morseDecB [indB]))
00274 {
00275 continue;
00276 }
00277 else if (!refA && refB && intersectSub
00278 (refinedB [indB], morseDecA [indA]))
00279 {
00280 continue;
00281 }
00282 else if (!refA && !refB)
00283 continue;
00284
00285
00286 BtoA [indB]. erase (std::find
00287 (BtoA [indB]. begin (),
00288 BtoA [indB]. end (), indA));
00289 AtoB [indA]. erase (begin + i);
00290 -- i;
00291 }
00292 }
00293
00294
00295 for (int i = 0; i < nSets; ++ i)
00296 {
00297 if (MtoN [i]. empty () || NtoM [i]. empty ())
00298 {
00299 sbug << "WARNING: The intersection became "
00300 "empty!!!\n";
00301 return false;
00302 }
00303 if ((MtoN [i]. size () > 1) ||
00304 (NtoM [i]. size () > 1))
00305 {
00306 sbug << "Note: No bijection in matching, "
00307 "even after refinements.\n";
00308 return false;
00309 }
00310 }
00311 }
00312
00313
00314 if (wrongIndM. size () != wrongIndN. size ())
00315 return false;
00316 int wrongIndSize = wrongIndM. size ();
00317 for (int i = 0; i < wrongIndSize; ++ i)
00318 {
00319 int number = MtoN [wrongIndM [i]] [0];
00320 bool found = false;
00321 for (int j = 0; j < wrongIndSize; ++ j)
00322 {
00323 if (wrongIndN [j] != number)
00324 continue;
00325 found = true;
00326 break;
00327 }
00328 if (!found)
00329 return false;
00330 }
00331
00332
00333 if (matchOrdering)
00334 {
00335
00336 chomp::homology::flatMatrix<char> orderM (nSets);
00337 chomp::homology::flatMatrix<char> orderN (nSets);
00338 for (int i = 0; i < nSets; ++ i)
00339 {
00340 for (int j = 0; j < nSets; ++ j)
00341 {
00342 orderM [i] [j] = morseDecM.
00343 connected (i, j) ? 1 : 0;
00344 orderN [i] [j] = morseDecN. connected
00345 (MtoN [i] [0], MtoN [j] [0]) ? 1 : 0;
00346 }
00347 }
00348
00349
00350 chomp::homology::transitiveClosure (orderM, nSets);
00351 chomp::homology::transitiveClosure (orderN, nSets);
00352
00353
00354 const char *memoryM = orderM. memory ();
00355 const char *memoryN = orderN. memory ();
00356 int memSize = nSets * nSets;
00357 for (int i = 0; i < memSize; ++ i)
00358 {
00359 if (*(memoryM ++) != *(memoryN ++))
00360 {
00361 sbug << "Note: Different Morse ordering.\n";
00362 return false;
00363 }
00364 }
00365
00366 }
00367
00368 return true;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 inline void matchMorseDecompositions (const parCubes ¶mBoxes,
00380 const std::vector<theMorseDecompositionType *> &morseDec,
00381
00382
00383
00384 const std::vector<theCubMapType *> &theCubMap1,
00385 const std::vector<std::vector<int> > &wrongIndices,
00386 const parCoord *parLeft, const parCoord *parRight,
00387 std::vector<std::vector<parCube> > &matchClasses)
00388 {
00389 using chomp::homology::sbug;
00390
00391
00392 parCoord sizes [paramDim];
00393 for (int i = 0; i < paramDim; ++ i)
00394 sizes [i] = parRight [i] - parLeft [i];
00395 MatchArray<parCoord,int> matchArray (paramDim, sizes, parLeft);
00396
00397
00398 int nBoxes = paramBoxes. size ();
00399
00400
00401 std::vector<std::vector<spcCubes> > refined (nBoxes);
00402
00403
00404
00405 for (int boxNumber = 0; boxNumber < nBoxes; ++ boxNumber)
00406 {
00407
00408 parCoord coord [paramDim];
00409 paramBoxes [boxNumber]. coord (coord);
00410
00411
00412 parCoord coordLeft [paramDim];
00413 parCoord coordRight [paramDim];
00414 for (int i = 0; i < paramDim; ++ i)
00415 {
00416 coordLeft [i] = coord [i] - 1;
00417 if (coordLeft [i] < parLeft [i])
00418 coordLeft [i] = parLeft [i];
00419 coordRight [i] = coord [i] + 2;
00420 if (coordRight [i] > parRight [i])
00421 coordRight [i] = parRight [i];
00422 }
00423
00424
00425 parRect neighbors (coordLeft, coordRight, paramDim);
00426 const parCoord *neighborCoord;
00427 while ((neighborCoord = neighbors. get ()) != 0)
00428 {
00429
00430
00431 int compare = 0;
00432 for (int i = 0; i < paramDim; ++ i)
00433 {
00434 if (neighborCoord [i] < coord [i])
00435 {
00436 compare = -1;
00437 break;
00438 }
00439 else if (neighborCoord [i] > coord [i])
00440 {
00441 compare = 1;
00442 break;
00443 }
00444 }
00445 if (compare >= 0)
00446 continue;
00447
00448
00449
00450 if (matchArray. joined (coord, neighborCoord))
00451 continue;
00452
00453
00454
00455 int neighborNumber = paramBoxes. getnumber
00456 (parCube (neighborCoord, paramDim));
00457 if (neighborNumber < 0)
00458 throw "Matching a non-existent neighbor.";
00459 sbug << "Matching " << parCube (coord, paramDim) <<
00460 " & " << parCube (neighborCoord, paramDim) <<
00461 "...\n";
00462 bool matchResult = matchMorseSets
00463 (*(morseDec [boxNumber]),
00464 wrongIndices [boxNumber],
00465 *(theCubMap1 [boxNumber]),
00466 refined [boxNumber],
00467 *(morseDec [neighborNumber]),
00468 wrongIndices [neighborNumber],
00469 *(theCubMap1 [neighborNumber]),
00470 refined [neighborNumber],
00471 compareMorseOrdering);
00472 if (matchResult == true)
00473 {
00474 sbug << "Success. :)\n";
00475 matchArray. join (coord, neighborCoord);
00476 }
00477 else
00478 {
00479 sbug << "Failure. :(\n";
00480 }
00481 }
00482 }
00483
00484
00485 matchArray. saveClasses (matchClasses);
00486
00487 return;
00488 }
00489
00490
00491 #endif // _CMGRAPHS_MATCHDEC_H_
00492