The Conley-Morse Graphs Software
matcharr.h
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2/// @file matcharr.h
3///
4/// Array for matching Morse decompositions.
5/// This file defines a class for storing a multi-dimensional array
6/// whose entries can be efficiently joined into chains which define
7/// separate classes of matching entries.
8///
9/// @author Pawel Pilarczyk
10/////////////////////////////////////////////////////////////////////////////
11
12// Copyright (C) 1997-2014 by Pawel Pilarczyk.
13//
14// This file is part of my research software package. This is free software:
15// you can redistribute it and/or modify it under the terms of the GNU
16// General Public License as published by the Free Software Foundation,
17// either version 3 of the License, or (at your option) any later version.
18//
19// This software is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22// GNU General Public License for more details.
23//
24// You should have received a copy of the GNU General Public License
25// along with this software; see the file "license.txt". If not,
26// please, see <https://www.gnu.org/licenses/>.
27
28// Started on November 16, 2006. Last revision: February 19, 2008.
29
30
31#ifndef _CMGRAPHS_MATCHARR_H_
32#define _CMGRAPHS_MATCHARR_H_
33
34
35// include some standard C++ header files
36#include <iostream>
37#include <fstream>
38#include <string>
39#include <sstream>
40#include <vector>
41#include <map>
42#include <algorithm>
43#include <cstring>
44
45// include selected header files from the CHomP library
46#include "chomp/system/config.h"
47#include "chomp/system/textfile.h"
48
49
50// --------------------------------------------------
51// ------------------- MATCHARRAY -------------------
52// --------------------------------------------------
53
54/// A multi-dimensional array with links forward/backward between
55/// the entries. Note that the type of integers
56/// provided as template's argument must be large enough
57/// to allow indexing of all the entries in a linear array.
58template <class CoordType, class IntType>
60{
61public:
62 /// The only allowed constructor in which the size of the array
63 /// and its dimension must be given.
64 /// Optionally the coordinates of the minimal corner may be provided.
65 MatchArray (int _dim, const CoordType *_sizes,
66 const CoordType *_corner = 0);
67
68 /// The destructor.
70
71 /// Joins the chains corresponding to the two parameter n-tuples.
72 void join (const CoordType *x, const CoordType *y);
73
74 /// Checks if the two parameters have already been joined, that is,
75 /// if they belong to the same chain.
76 /// Returns "true" if yes, "false" if not.
77 bool joined (const CoordType *x, const CoordType *y) const;
78
79 /// Saves the equivalence classes larger than 1 element
80 /// to the provided vector of vectors (the classes are appended).
81 /// The type of coordinates of the cube type must match "CoordType".
82 template <class CubeType>
83 void saveClasses (std::vector<std::vector<CubeType> > &matchClasses)
84 const;
85
86 /// Saves the sets to separate files. Sorts the sets by their size.
87 void saveSets (const char *prefix) const;
88
89private:
90 /// The copy constructor is not allowed.
92
93 /// The assignment operator is not allowed.
95
96 /// Backward links for chains.
97 IntType *link1;
98
99 /// Forward links for chains.
100 IntType *link2;
101
102 /// The unique number for each chain. This is stored here
103 /// to speed up the verification if two boxes are in the same chain.
104 IntType *num;
105
106 /// The size of the multi-dimensional array in each direction.
107 CoordType *sizes;
108
109 /// The coordinates of the minimal corner of the array if any.
110 CoordType *corner;
111
112 /// The dimension of the array.
113 int dim;
114
115 /// The length of the allocated memory arrays.
117
118 /// Translates a flat offset array into a multidimensional one.
119 void link2coords (IntType link, CoordType *x) const;
120
121 /// Computes the memory offset that corresponds to the given
122 /// multidimensional position in the array.
123 IntType coords2link (const CoordType *x) const;
124
125 /// A small class whose objects store an IntType object
126 /// and an int value. The objects are compared by the value.
127 struct pair2
128 {
129 pair2 (IntType _x, int _value): x (_x), value (_value) {}
130 IntType x;
131 int value;
132 bool operator < (const pair2 &other) const
133 {
134 return (this -> value < other. value);
135 }
136 }; /* struct pair2 */
137
138 /// Retrieves a set of first elements of all the chains
139 /// which have at least two elements.
140 /// The list is sorted according to the lengths of the chains
141 /// in the descending order.
143 &chains) const;
144
145 /// Saves one set to a file.
146 void saveSet (const char *prefix, int counter, int pos,
147 CoordType *workspace, int ndigits) const;
148
149 /// Joins two sets, given the offsets in the flat arrays.
150 void join (IntType xpos, IntType ypos);
151
152}; /* class MatchArray */
153
154// --------------------------------------------------
155
156template <class CoordType, class IntType>
158 const CoordType *_sizes, const CoordType *_corner):
159 link1 (0), link2 (0), num (0), sizes (0), corner (0),
160 dim (_dim), length (0)
161{
162 if (!_sizes)
163 throw "Undefined array sizes.";
164 if (_dim <= 0)
165 throw "Non-positive dimension.";
166 sizes = new CoordType [dim];
167 length = 1;
168 for (int i = 0; i < dim; ++ i)
169 {
170 sizes [i] = _sizes [i];
171 long prevLength = length;
172 length *= sizes [i];
173 if (length < prevLength)
174 throw "Too large matching array requested.";
175 }
176 if (_corner)
177 {
178 corner = new CoordType [dim];
179 for (int i = 0; i < dim; ++ i)
180 corner [i] = _corner [i];
181 }
182 link1 = new IntType [length];
183 link2 = new IntType [length];
184 num = new IntType [length];
185 for (int offset = 0; offset < length; ++ offset)
186 {
187 num [offset] = offset;
188 link1 [offset] = -1;
189 link2 [offset] = -1;
190 }
191
192 if (false) // DEBUG
193 {
194 CoordType *c = new CoordType [dim];
195 for (int i = 0; i < dim; ++ i)
196 c [i] = corner ? corner [i] : 0;
197 for (int offset = 0; offset < length; ++ offset)
198 {
199 // verify the correctness of the entry
200 if (coords2link (c) != offset)
201 chomp::homology::sbug << "Mismatch at "
202 "array offset " << offset <<
203 ": " << coords2link (c) << ".\n";
204 // increase the multi-counter
205 int i = 0;
206 while (1)
207 {
208 if (++ c [i] < sizes [i] +
209 (corner ? corner [i] : 0))
210 break;
211 c [i] = corner ? corner [i] : 0;
212 ++ i;
213 if (i >= dim)
214 break;
215 }
216 }
217 delete [] c;
218 // chomp::homology::sbug << "Note: Array offsets verified "
219 // "successfully.\n";
220 }
221
222 return;
223} /* MatchArray::MatchArray */
224
225template <class CoordType, class IntType>
227{
228 if (corner)
229 delete [] corner;
230 delete [] sizes;
231 delete [] num;
232 delete [] link2;
233 delete [] link1;
234 return;
235} /* MatchArray::~MatchArray */
236
237template <class CoordType, class IntType>
240{
241 throw "Array assignment operator not allowed.";
242 return *this;
243} /* MatchArray::operator = */
244
245template <class CoordType, class IntType>
248{
249 throw "Array copy constructor not allowed.";
250 return;
251} /* MatchArray::MatchArray */
252
253// --------------------------------------------------
254
255template <class CoordType, class IntType>
257 CoordType *x) const
258{
259 int n = link;
260 for (int i = 0; i < dim - 1; ++ i)
261 {
262 x [i] = n % sizes [i] + (corner ? corner [i] : 0);
263 n /= sizes [i];
264 }
265 x [dim - 1] = n % sizes [dim - 1] + (corner ? corner [dim - 1] : 0);
266 return;
267} /* MatchArray::link2coords */
268
269template <class CoordType, class IntType>
271 (const CoordType *x) const
272{
273 IntType n = x [dim - 1] - (corner ? corner [dim - 1] : 0);
274 for (int i = dim - 2; i >= 0; -- i)
275 {
276 n *= sizes [i];
277 n += x [i] - (corner ? corner [i] : 0);
278 }
279 return n;
280} /* MatchArray::coords2link */
281
282template <class CoordType, class IntType>
283inline void MatchArray<CoordType,IntType>::join (IntType xpos, IntType ypos)
284{
285 if (num [xpos] == num [ypos])
286 return;
287 IntType newnum = num [xpos];
288 while (link1 [xpos] >= 0)
289 xpos = link1 [xpos];
290 while (link2 [ypos] >= 0)
291 ypos = link2 [ypos];
292 link1 [xpos] = ypos;
293 link2 [ypos] = xpos;
294 while (1)
295 {
296 num [ypos] = newnum;
297 if (link1 [ypos] < 0)
298 break;
299 ypos = link1 [ypos];
300 }
301 return;
302} /* MatchArray::join */
303
304// --------------------------------------------------
305
306template <class CoordType, class IntType>
307inline void MatchArray<CoordType,IntType>::saveSet (const char *prefix,
308 int counter, int pos, CoordType *workspace, int ndigits) const
309{
310 // create the file name and open the file
311 std::ostringstream fname;
312 fname << prefix;
313 int ten = 1;
314 for (int i = 1; i < ndigits; ++ i)
315 ten *= 10;
316 while (counter < ten)
317 {
318 fname << '0';
319 ten /= 10;
320 }
321 fname << counter << ".cub";
322 std::ofstream out (fname. str (). c_str ());
323
324 // go to the beginning of the list
325 while (link1 [pos] >= 0)
326 pos = link1 [pos];
327
328 // write all the elements of the list to the file
329 while (pos >= 0)
330 {
331 link2coords (pos, workspace);
332 for (int i = 0; i < dim; ++ i)
333 out << (i ? "," : "(") << workspace [i];
334 out << ")\n";
335 // link1 [x] [y] = -1;
336 // IntType link = link2 [pos];
337 // link2 [pos] = -1;
338 // pos = link;
339 pos = link2 [pos];
340 }
341 return;
342} /* MatchArray::saveSet */
343
344// --------------------------------------------------
345
346//template <class CoordType, class IntType>
347//inline bool operator <
348// (const typename MatchArray<CoordType,IntType>::pair2 &x,
349// const typename MatchArray<CoordType,IntType>::pair2 &y)
350//{
351// return (x. value < y. value);
352//} /* operator < */
353
354template <class CoordType, class IntType>
355inline void MatchArray<CoordType,IntType>::join (const CoordType *x,
356 const CoordType *y)
357{
358 join (coords2link (x), coords2link (y));
359 return;
360} /* MatchArray::join */
361
362template <class CoordType, class IntType>
363inline bool MatchArray<CoordType,IntType>::joined (const CoordType *x,
364 const CoordType *y) const
365{
366 int xpos = coords2link (x);
367 if (xpos < 0)
368 return false;
369 int ypos = coords2link (y);
370 if (ypos < 0)
371 return false;
372 return (num [xpos] == num [ypos]);
373} /* MatchArray::joined */
374
375template <class CoordType, class IntType>
377 (std::vector<MatchArray<CoordType,IntType>::pair2> &chains) const
378{
379 // create a list of chain beginnings
380 chomp::homology::sbug << "Analyzing the sets of matched boxes... ";
381 for (IntType cur = 0; cur < length; ++ cur)
382 {
383 if ((link1 [cur] < 0) && (link2 [cur] >= 0))
384 {
385 int setsize = 0;
386 IntType pos = cur;
387 while (pos >= 0)
388 {
389 ++ setsize;
390 pos = link2 [pos];
391 }
392 chains. push_back (pair2 (cur, setsize));
393 }
394 }
395 chomp::homology::sbug << chains. size () << " nontrivial classes.\n";
396
397 // sort the list of chain beginnings
398 std::sort (chains. begin (), chains. end ());
399
400 return;
401} /* MatchArray::getChains */
402
403template <class CoordType, class IntType>
404inline void MatchArray<CoordType,IntType>::saveSets (const char *prefix)
405 const
406{
407 // create a list of chain beginnings
408 std::vector<pair2> sets;
409 this -> getChains (sets);
410
411 // compute the number of digits to be used in the file names
412 int ndigits = 1;
413 unsigned ten = 10;
414 while (sets. size () >= ten)
415 {
416 ++ ndigits;
417 ten *= 10;
418 }
419
420 // write the sets to files
421 int counter = 0;
422 chomp::homology::sbug << "Saving the nontrivial "
423 "equivalence classes... ";
424 CoordType *workspace = new CoordType [dim];
425 for (int i = sets. size () - 1; i >= 0; -- i)
426 {
427 saveSet (prefix, ++ counter, sets [i]. x, workspace,
428 ndigits);
429 }
430 delete [] workspace;
431 chomp::homology::sout << "Done.\n";
432
433 return;
434} /* MatchArray::saveSets */
435
436template <class CoordType, class IntType>
437template <class CubeType>
439 (std::vector<std::vector<CubeType> > &matchClasses) const
440{
441 // create a list of chain beginnings
442 std::vector<pair2> sets;
443 getChains (sets);
444
445 // create vectors of cubes and add them to the given one
446 CoordType *coord = new CoordType [dim];
447 std::vector<CubeType> emptyVector;
448 for (int i = sets. size () - 1; i >= 0; -- i)
449 {
450 // go to the beginning of the list
451 IntType pos = sets [i]. x;
452 while (link1 [pos] >= 0)
453 pos = link1 [pos];
454
455 // create a vector with all the elements of the list
456 matchClasses. push_back (emptyVector);
457 std::vector<CubeType> &vect =
458 matchClasses [matchClasses. size () - 1];
459 vect. resize (sets [i]. value);
460 int j = 0;
461 while (pos >= 0)
462 {
463 link2coords (pos, coord);
464 vect [j ++] = CubeType (coord, dim);
465 pos = link2 [pos];
466 }
467 }
468 delete [] coord;
469 return;
470} /* MatchArray::saveClasses */
471
472
473#endif // _CMGRAPHS_MATCHARR_H
474
A multi-dimensional array with links forward/backward between the entries.
Definition: matcharr.h:60
void saveSet(const char *prefix, int counter, int pos, CoordType *workspace, int ndigits) const
Saves one set to a file.
Definition: matcharr.h:307
MatchArray(int _dim, const CoordType *_sizes, const CoordType *_corner=0)
The only allowed constructor in which the size of the array and its dimension must be given.
Definition: matcharr.h:157
void link2coords(IntType link, CoordType *x) const
Translates a flat offset array into a multidimensional one.
Definition: matcharr.h:256
void saveSets(const char *prefix) const
Saves the sets to separate files. Sorts the sets by their size.
Definition: matcharr.h:404
IntType * link2
Forward links for chains.
Definition: matcharr.h:100
IntType * link1
Backward links for chains.
Definition: matcharr.h:97
void join(IntType xpos, IntType ypos)
Joins two sets, given the offsets in the flat arrays.
Definition: matcharr.h:283
MatchArray & operator=(const MatchArray< CoordType, IntType > &a)
The assignment operator is not allowed.
Definition: matcharr.h:239
IntType * num
The unique number for each chain.
Definition: matcharr.h:104
void saveClasses(std::vector< std::vector< CubeType > > &matchClasses) const
Saves the equivalence classes larger than 1 element to the provided vector of vectors (the classes ar...
Definition: matcharr.h:439
MatchArray(const MatchArray< CoordType, IntType > &a)
The copy constructor is not allowed.
Definition: matcharr.h:247
int length
The length of the allocated memory arrays.
Definition: matcharr.h:116
~MatchArray()
The destructor.
Definition: matcharr.h:226
CoordType * corner
The coordinates of the minimal corner of the array if any.
Definition: matcharr.h:110
IntType coords2link(const CoordType *x) const
Computes the memory offset that corresponds to the given multidimensional position in the array.
Definition: matcharr.h:271
void join(const CoordType *x, const CoordType *y)
Joins the chains corresponding to the two parameter n-tuples.
Definition: matcharr.h:355
int dim
The dimension of the array.
Definition: matcharr.h:113
CoordType * sizes
The size of the multi-dimensional array in each direction.
Definition: matcharr.h:107
void getChains(std::vector< MatchArray< CoordType, IntType >::pair2 > &chains) const
Retrieves a set of first elements of all the chains which have at least two elements.
Definition: matcharr.h:377
bool joined(const CoordType *x, const CoordType *y) const
Checks if the two parameters have already been joined, that is, if they belong to the same chain.
Definition: matcharr.h:363
A small class whose objects store an IntType object and an int value.
Definition: matcharr.h:128
pair2(IntType _x, int _value)
Definition: matcharr.h:129
bool operator<(const pair2 &other) const
Definition: matcharr.h:132