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 #ifndef _CMGRAPHS_MATCHARR_H_
00033 #define _CMGRAPHS_MATCHARR_H_
00034
00035
00036
00037 #include <iostream>
00038 #include <fstream>
00039 #include <string>
00040 #include <sstream>
00041 #include <vector>
00042 #include <map>
00043 #include <algorithm>
00044 #include <cstring>
00045
00046
00047 #include "chomp/system/config.h"
00048 #include "chomp/system/textfile.h"
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 template <class CoordType, class IntType>
00060 class MatchArray
00061 {
00062 public:
00063
00064
00065
00066 MatchArray (int _dim, const CoordType *_sizes,
00067 const CoordType *_corner = 0);
00068
00069
00070 ~MatchArray ();
00071
00072
00073 void join (const CoordType *x, const CoordType *y);
00074
00075
00076
00077
00078 bool joined (const CoordType *x, const CoordType *y) const;
00079
00080
00081
00082
00083 template <class CubeType>
00084 void saveClasses (std::vector<std::vector<CubeType> > &matchClasses)
00085 const;
00086
00087
00088 void saveSets (const char *prefix) const;
00089
00090 private:
00091
00092 MatchArray (const MatchArray<CoordType,IntType> &a);
00093
00094
00095 MatchArray &operator = (const MatchArray<CoordType,IntType> &a);
00096
00097
00098 IntType *link1;
00099
00100
00101 IntType *link2;
00102
00103
00104
00105 IntType *num;
00106
00107
00108 CoordType *sizes;
00109
00110
00111 CoordType *corner;
00112
00113
00114 int dim;
00115
00116
00117 int length;
00118
00119
00120 void link2coords (IntType link, CoordType *x) const;
00121
00122
00123
00124 IntType coords2link (const CoordType *x) const;
00125
00126
00127
00128 struct pair2
00129 {
00130 pair2 (IntType _x, int _value): x (_x), value (_value) {}
00131 IntType x;
00132 int value;
00133 bool operator < (const pair2 &other) const
00134 {
00135 return (this -> value < other. value);
00136 }
00137 };
00138
00139
00140
00141
00142
00143 void getChains (std::vector <MatchArray<CoordType,IntType>::pair2>
00144 &chains) const;
00145
00146
00147 void saveSet (const char *prefix, int counter, int pos,
00148 CoordType *workspace, int ndigits) const;
00149
00150
00151 void join (IntType xpos, IntType ypos);
00152
00153 };
00154
00155
00156
00157 template <class CoordType, class IntType>
00158 inline MatchArray<CoordType,IntType>::MatchArray (int _dim,
00159 const CoordType *_sizes, const CoordType *_corner):
00160 link1 (0), link2 (0), num (0), sizes (0), corner (0),
00161 dim (_dim), length (0)
00162 {
00163 if (!_sizes)
00164 throw "Undefined array sizes.";
00165 if (_dim <= 0)
00166 throw "Non-positive dimension.";
00167 sizes = new CoordType [dim];
00168 length = 1;
00169 for (int i = 0; i < dim; ++ i)
00170 {
00171 sizes [i] = _sizes [i];
00172 long prevLength = length;
00173 length *= sizes [i];
00174 if (length < prevLength)
00175 throw "Too large matching array requested.";
00176 }
00177 if (_corner)
00178 {
00179 corner = new CoordType [dim];
00180 for (int i = 0; i < dim; ++ i)
00181 corner [i] = _corner [i];
00182 }
00183 link1 = new IntType [length];
00184 link2 = new IntType [length];
00185 num = new IntType [length];
00186 for (int offset = 0; offset < length; ++ offset)
00187 {
00188 num [offset] = offset;
00189 link1 [offset] = -1;
00190 link2 [offset] = -1;
00191 }
00192
00193 if (false)
00194 {
00195 CoordType *c = new CoordType [dim];
00196 for (int i = 0; i < dim; ++ i)
00197 c [i] = corner ? corner [i] : 0;
00198 for (int offset = 0; offset < length; ++ offset)
00199 {
00200
00201 if (coords2link (c) != offset)
00202 chomp::homology::sbug << "Mismatch at "
00203 "array offset " << offset <<
00204 ": " << coords2link (c) << ".\n";
00205
00206 int i = 0;
00207 while (1)
00208 {
00209 if (++ c [i] < sizes [i] +
00210 (corner ? corner [i] : 0))
00211 break;
00212 c [i] = corner ? corner [i] : 0;
00213 ++ i;
00214 if (i >= dim)
00215 break;
00216 }
00217 }
00218 delete [] c;
00219
00220
00221 }
00222
00223 return;
00224 }
00225
00226 template <class CoordType, class IntType>
00227 inline MatchArray<CoordType,IntType>::~MatchArray ()
00228 {
00229 if (corner)
00230 delete [] corner;
00231 delete [] sizes;
00232 delete [] num;
00233 delete [] link2;
00234 delete [] link1;
00235 return;
00236 }
00237
00238 template <class CoordType, class IntType>
00239 inline MatchArray<CoordType,IntType> &MatchArray<CoordType,IntType>::
00240 operator = (const MatchArray &)
00241 {
00242 throw "Array assignment operator not allowed.";
00243 return *this;
00244 }
00245
00246 template <class CoordType, class IntType>
00247 inline MatchArray<CoordType,IntType>::MatchArray
00248 (const MatchArray<CoordType,IntType> &)
00249 {
00250 throw "Array copy constructor not allowed.";
00251 return;
00252 }
00253
00254
00255
00256 template <class CoordType, class IntType>
00257 inline void MatchArray<CoordType,IntType>::link2coords (IntType link,
00258 CoordType *x) const
00259 {
00260 int n = link;
00261 for (int i = 0; i < dim - 1; ++ i)
00262 {
00263 x [i] = n % sizes [i] + (corner ? corner [i] : 0);
00264 n /= sizes [i];
00265 }
00266 x [dim - 1] = n % sizes [dim - 1] + (corner ? corner [dim - 1] : 0);
00267 return;
00268 }
00269
00270 template <class CoordType, class IntType>
00271 inline IntType MatchArray<CoordType,IntType>::coords2link
00272 (const CoordType *x) const
00273 {
00274 IntType n = x [dim - 1] - (corner ? corner [dim - 1] : 0);
00275 for (int i = dim - 2; i >= 0; -- i)
00276 {
00277 n *= sizes [i];
00278 n += x [i] - (corner ? corner [i] : 0);
00279 }
00280 return n;
00281 }
00282
00283 template <class CoordType, class IntType>
00284 inline void MatchArray<CoordType,IntType>::join (IntType xpos, IntType ypos)
00285 {
00286 if (num [xpos] == num [ypos])
00287 return;
00288 IntType newnum = num [xpos];
00289 while (link1 [xpos] >= 0)
00290 xpos = link1 [xpos];
00291 while (link2 [ypos] >= 0)
00292 ypos = link2 [ypos];
00293 link1 [xpos] = ypos;
00294 link2 [ypos] = xpos;
00295 while (1)
00296 {
00297 num [ypos] = newnum;
00298 if (link1 [ypos] < 0)
00299 break;
00300 ypos = link1 [ypos];
00301 }
00302 return;
00303 }
00304
00305
00306
00307 template <class CoordType, class IntType>
00308 inline void MatchArray<CoordType,IntType>::saveSet (const char *prefix,
00309 int counter, int pos, CoordType *workspace, int ndigits) const
00310 {
00311
00312 std::ostringstream fname;
00313 fname << prefix;
00314 int ten = 1;
00315 for (int i = 1; i < ndigits; ++ i)
00316 ten *= 10;
00317 while (counter < ten)
00318 {
00319 fname << '0';
00320 ten /= 10;
00321 }
00322 fname << counter << ".cub";
00323 std::ofstream out (fname. str (). c_str ());
00324
00325
00326 while (link1 [pos] >= 0)
00327 pos = link1 [pos];
00328
00329
00330 while (pos >= 0)
00331 {
00332 link2coords (pos, workspace);
00333 for (int i = 0; i < dim; ++ i)
00334 out << (i ? "," : "(") << workspace [i];
00335 out << ")\n";
00336
00337
00338
00339
00340 pos = link2 [pos];
00341 }
00342 return;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 template <class CoordType, class IntType>
00356 inline void MatchArray<CoordType,IntType>::join (const CoordType *x,
00357 const CoordType *y)
00358 {
00359 join (coords2link (x), coords2link (y));
00360 return;
00361 }
00362
00363 template <class CoordType, class IntType>
00364 inline bool MatchArray<CoordType,IntType>::joined (const CoordType *x,
00365 const CoordType *y) const
00366 {
00367 int xpos = coords2link (x);
00368 if (xpos < 0)
00369 return false;
00370 int ypos = coords2link (y);
00371 if (ypos < 0)
00372 return false;
00373 return (num [xpos] == num [ypos]);
00374 }
00375
00376 template <class CoordType, class IntType>
00377 inline void MatchArray<CoordType,IntType>::getChains
00378 (std::vector<MatchArray<CoordType,IntType>::pair2> &chains) const
00379 {
00380
00381 chomp::homology::sbug << "Analyzing the sets of matched boxes... ";
00382 for (IntType cur = 0; cur < length; ++ cur)
00383 {
00384 if ((link1 [cur] < 0) && (link2 [cur] >= 0))
00385 {
00386 int setsize = 0;
00387 IntType pos = cur;
00388 while (pos >= 0)
00389 {
00390 ++ setsize;
00391 pos = link2 [pos];
00392 }
00393 chains. push_back (pair2 (cur, setsize));
00394 }
00395 }
00396 chomp::homology::sbug << chains. size () << " nontrivial classes.\n";
00397
00398
00399 std::sort (chains. begin (), chains. end ());
00400
00401 return;
00402 }
00403
00404 template <class CoordType, class IntType>
00405 inline void MatchArray<CoordType,IntType>::saveSets (const char *prefix)
00406 const
00407 {
00408
00409 std::vector<pair2> sets;
00410 this -> getChains (sets);
00411
00412
00413 int ndigits = 1;
00414 unsigned ten = 10;
00415 while (sets. size () >= ten)
00416 {
00417 ++ ndigits;
00418 ten *= 10;
00419 }
00420
00421
00422 int counter = 0;
00423 chomp::homology::sbug << "Saving the nontrivial "
00424 "equivalence classes... ";
00425 CoordType *workspace = new CoordType [dim];
00426 for (int i = sets. size () - 1; i >= 0; -- i)
00427 {
00428 saveSet (prefix, ++ counter, sets [i]. x, workspace,
00429 ndigits);
00430 }
00431 delete [] workspace;
00432 chomp::homology::sout << "Done.\n";
00433
00434 return;
00435 }
00436
00437 template <class CoordType, class IntType>
00438 template <class CubeType>
00439 inline void MatchArray<CoordType,IntType>::saveClasses
00440 (std::vector<std::vector<CubeType> > &matchClasses) const
00441 {
00442
00443 std::vector<pair2> sets;
00444 getChains (sets);
00445
00446
00447 CoordType *coord = new CoordType [dim];
00448 std::vector<CubeType> emptyVector;
00449 for (int i = sets. size () - 1; i >= 0; -- i)
00450 {
00451
00452 IntType pos = sets [i]. x;
00453 while (link1 [pos] >= 0)
00454 pos = link1 [pos];
00455
00456
00457 matchClasses. push_back (emptyVector);
00458 std::vector<CubeType> &vect =
00459 matchClasses [matchClasses. size () - 1];
00460 vect. resize (sets [i]. value);
00461 int j = 0;
00462 while (pos >= 0)
00463 {
00464 link2coords (pos, coord);
00465 vect [j ++] = CubeType (coord, dim);
00466 pos = link2 [pos];
00467 }
00468 }
00469 delete [] coord;
00470 return;
00471 }
00472
00473
00474 #endif // _CMGRAPHS_MATCHARR_H
00475