The Conley-Morse Graphs Software
indcache.h
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2///
3/// @file indcache.h
4///
5/// Cached Conley indices for a Morse decomposition.
6/// This file contains the definition of a class for caching computed
7/// Conley indices for a Morse decomposition. The Conley indices can be
8/// saved to a file or retrieved from a file, including the information
9/// on a nontrivial invariant part for Morse sets with the trivial index.
10///
11/// @author Pawel Pilarczyk
12///
13/////////////////////////////////////////////////////////////////////////////
14
15// Copyright (C) 1997-2014 by Pawel Pilarczyk.
16//
17// This file is part of my research software package. This is free software:
18// you can redistribute it and/or modify it under the terms of the GNU
19// General Public License as published by the Free Software Foundation,
20// either version 3 of the License, or (at your option) any later version.
21//
22// This software is distributed in the hope that it will be useful,
23// but WITHOUT ANY WARRANTY; without even the implied warranty of
24// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25// GNU General Public License for more details.
26//
27// You should have received a copy of the GNU General Public License
28// along with this software; see the file "license.txt". If not,
29// please, see <https://www.gnu.org/licenses/>.
30
31// Started on February 12, 2007. Last revision: July 11, 2014.
32
33
34#ifndef _CMGRAPHS_INDCACHE_H_
35#define _CMGRAPHS_INDCACHE_H_
36
37
38// include some standard C++ header files
39#include <fstream>
40#include <string>
41#include <sstream>
42
43// include selected header files from the CHomP library
44#include "chomp/system/textfile.h"
45#include "chomp/cubes/pointset.h"
46
47// include local header files
48#include "config.h"
49#include "typedefs.h"
50#include "conindex.h"
51#include "morsedec.h"
52#include "typedyns.h"
53#include "bytecompr.h"
54#include "byteutil.h"
55
56
57// --------------------------------------------------
58// ------------- cached Conley indices --------------
59// --------------------------------------------------
60
61/// Cached information on the Conley-Morse decompositions
62/// which contains information on computed Conley indices
63/// for Morse sets and also the information on whether the invariant part
64/// was proved to be empty for the sets with the trivial index.
66{
67public:
68 /// The constructor of an empty cached information structure
69 /// for the given number of Morse sets.
70 IndexCache (int nSets);
71
72 /// Reads the cached information from a file, matches it
73 /// with the given Morse decomposition and sets the Conley indices.
74 /// Returns 0 if succeeded, or -1 if failed.
75 int read (const std::string &fileName,
77
78 /// Writes the cached information for the given Morse decomposition
79 /// to a file.
80 /// Returns 0 if succeeded, 1 if the file already exists,
81 /// or -1 in the case of failure.
82 int write (const std::string &fileName,
83 const theMorseDecompositionType &morseDec) const;
84
85 /// The destructor of a cached information structure.
86 ~IndexCache ();
87
88 /// The information on whether the invariant part of the given set
89 /// has been proven to be empty.
90 std::vector<bool> emptyInv;
91
92 /// The information on whether the given Morse set is an attractor
93 /// in the sense that its image is contained in itself.
94 std::vector<bool> attractor;
95
96 /// The information on whether the given index could not be computed
97 /// because of a problem with isolation.
98 std::vector<bool> wrongIndex;
99
100 /// The information on whether the computation of the given index
101 /// was skipped due to the limit on the size of the set.
102 std::vector<bool> skipped;
103
104}; /* class IndexCache */
105
106// --------------------------------------------------
107
108inline IndexCache::IndexCache (int nSets): emptyInv (nSets, false),
109 attractor (nSets, false), wrongIndex (nSets, false),
110 skipped (nSets, false)
111{
112 return;
113} /* IndexCache::IndexCache */
114
116{
117 return;
118} /* IndexCache::IndexCache */
119
120int IndexCache::read (const std::string &fileName,
122{
123 using chomp::homology::ignoreline;
124 using chomp::homology::ignorecomments;
125 using chomp::homology::sbug;
126
127 // open the file and read the cached index information from
128 std::ifstream inFile (fileName. c_str ());
129 if (!inFile)
130 return -1;
131 std::string str;
132 // if this is a bzip2-compressed file then decompress it
133 if (inFile. peek () == 'B')
134 {
135 ByteDecompressor inDecompr (inFile);
136 inDecompr >> str;
137 inDecompr. close ();
138 }
139 // otherwise read the contents of the file directly
140 else
141 {
142 std::getline (inFile, str, '\0');
143 }
144 inFile. close ();
145
146 // create a string stream to decode the index information from
147 std::istringstream in (str);
148 ignorecomments (in);
149
150 // read the number of Morse sets and make sure that it is correct
151 int nSets = -1;
152 in >> nSets;
153 ignorecomments (in);
154 if (nSets != morseDec. count ())
155 {
156 sbug << "Wrong number of Morse sets: " << nSets <<
157 " instead of " << morseDec. count () << ".\n";
158 return -1;
159 }
160
161 // prepare variables to read for each Morse set
162 int number = -1;
163 int empty = -1;
164 int attr = -1;
165 int wrong = -1;
166 int skip = -1;
167 int nCubes = -1;
168 spcCube reprCube;
170 int countItems = 0;
171
172 // prepare counters and matched bits to verify correctness
173 int countSets = 0;
174 std::vector<bool> matched (nSets, false);
175 bool found = false;
176
177 // read the Conley index and other information for each Morse set
178 while (1)
179 {
180 // read the control character which determines
181 // the kind of information to be read
182 int character = in. get ();
183 ignorecomments (in);
184 if (countSets && (character == 'M'))
185 character = 0x100;
186
187 switch (character)
188 {
189 // save the information previously gathered
190 case EOF:
191 case 0x100:
192 // make sure the number of items read is good
193 if (countItems < 7)
194 {
195 sbug << "Only " << countItems << " elements "
196 "read, at least 7 expected.\n";
197 return -1;
198 }
199
200 // find the Morse set which corresponds to this one
201 // and fill in the corresponding information
202 found = false;
203 for (int setNum = 0; setNum < nSets; ++ setNum)
204 {
205 if (matched [setNum])
206 continue;
207 if (morseDec [setNum]. size () != nCubes)
208 continue;
209 if (!morseDec [setNum]. check (reprCube))
210 continue;
211 matched [setNum] = true;
212 emptyInv [setNum] = (empty == 1);
213 attractor [setNum] = (attr == 1);
214 wrongIndex [setNum] = (wrong == 1);
215 skipped [setNum] = (skip == 1);
216 morseDec. setindex (setNum, ind);
217 found = true;
218 break;
219 }
220
221 // return error code if the Morse set was not matched
222 if (!found)
223 {
224 sbug << "Morse set no. " << number <<
225 " could not be matched with any "
226 "Morse set in the Morse dec.\n";
227 return -1;
228 }
229
230 // quit if this is the end of the data
231 if (character == EOF)
232 {
233 if (countSets == nSets)
234 return 0;
235 sbug << "Cached information for " <<
236 countSets << " Morse sets found, " <<
237 nSets << " expected.\n";
238 return -1;
239 }
240
241 // reset the variables
242 number = -1;
243 empty = -1;
244 attr = -1;
245 wrong = -1;
246 skip = -1;
247 nCubes = -1;
248 countItems = 0;
249 // [no 'break' after this case...]
250
251 // verify the number of the subsequent Morse set
252 case 'M':
253 in >> number;
254 ignorecomments (in);
255 if (number != countSets)
256 {
257 sbug << "Wrong Morse set number: " <<
258 number << " (" << countSets <<
259 " expected).\n";
260 return -1;
261 }
262 ++ countSets;
263 ++ countItems;
264 break;
265
266 // check if the invariant part of this set is empty or not
267 case 'E':
268 in >> empty;
269 ignorecomments (in);
270 if ((empty != 0) && (empty != 1))
271 {
272 sbug << "The number 0 or 1 expected "
273 "for 'emptyInv', " << empty <<
274 " found.\n";
275 return -1;
276 }
277 ++ countItems;
278 break;
279
280 // check if this is an attractor
281 case 'A':
282 in >> attr;
283 ignorecomments (in);
284 if ((attr != 0) && (attr != 1))
285 {
286 sbug << "The number 0 or 1 expected "
287 "for 'attractor', " << attr <<
288 " found.\n";
289 return -1;
290 }
291 ++ countItems;
292 break;
293
294 // check if the Morse set is wrong (no isolation)
295 case 'W':
296 in >> wrong;
297 ignorecomments (in);
298 if ((wrong != 0) && (wrong != 1))
299 {
300 sbug << "The number 0 or 1 expected "
301 "for 'wrong index', " << wrong <<
302 " found.\n";
303 return -1;
304 }
305 ++ countItems;
306 break;
307
308 // check if the computation for this set was skipped or not
309 case 'S':
310 in >> skip;
311 ignorecomments (in);
312 if ((skip != 0) && (skip != 1))
313 {
314 sbug << "The number 0 or 1 expected "
315 "for 'skipped index', " << skip <<
316 " found.\n";
317 return -1;
318 }
319 ++ countItems;
320 break;
321
322 // acquire the number of cubes in the Morse set
323 case 'N':
324 in >> nCubes;
325 ignorecomments (in);
326 if (nCubes < 0)
327 {
328 sbug << "Negative number of cubes found.\n";
329 return -1;
330 }
331 ++ countItems;
332 break;
333
334 // read a representative cube from the Morse set
335 case 'Q':
336 // make sure that a cube is waiting at the input
337 if (in. peek () != '(')
338 {
339 sbug << "An opening parenthesis of a cube "
340 "not present.\n";
341 return -1;
342 }
343
344 in >> reprCube;
345 ignorecomments (in);
346 ++ countItems;
347 break;
348
349 // read the Conley index
350 case 'I':
351 in >> ind;
352 ignorecomments (in);
353 ++ countItems;
354 break;
355
356 // ignore any unsupported data (for backwards compatibility)
357 default:
358 ignoreline (in);
359 ignorecomments (in);
360 break;
361 }
362 }
363
364 return 0;
365} /* IndexCache::read */
366
367int IndexCache::write (const std::string &fileName,
368 const theMorseDecompositionType &morseDec) const
369{
370 // create a string stream to write the cached index information to
371 std::ostringstream out;
372
373 out << "; Cached information with Conley indices "
374 "for a Morse decomposition.\n";
375
376 // write the number of Morse sets
377 int nSets = morseDec. count ();
378 out << "; The number of Morse sets:\n";
379 out << nSets << "\n";
380
381 // write the description of the information
382 out << "; -----\n";
383 out << "; M - the consecutive number of a Morse set\n";
384 out << "; E - 1 if the invariant set is empty, 0 if unknown\n";
385 out << "; A - 1 if this is an attractor, 0 if not or unknown\n";
386 out << "; W - 1 if the index is wrong (no isolation), 0 if good\n";
387 out << "; S - 1 if the index computation was skipped, 0 otherwise\n";
388 out << "; N - the number of cubes in the Morse set\n";
389 out << "; Q - a representative cube\n";
390 out << "; I - the Conley index encoded in numbers\n";
391
392 // write the Conley index and other information for each Morse set
393 for (int n = 0; n < nSets; ++ n)
394 {
395 out << "; -----\n";
396 out << "M " << n << "\n";
397 out << "E " << (emptyInv [n] ? 1 : 0) << "\n";
398 out << "A " << (attractor [n] ? 1 : 0) << "\n";
399 out << "W " << (wrongIndex [n] ? 1 : 0) << "\n";
400 out << "S " << (skipped [n] ? 1 : 0) << "\n";
401 out << "N " << morseDec [n]. size () << "\n";
402 out << "Q " << morseDec [n] [0] << "\n";
403 out << "I " << morseDec. index (n) << "\n";
404 }
405
406 // write the string to the output file
407 std::ofstream outFile (fileName. c_str ());
408 if (!outFile)
409 return -1;
410#ifdef CONFIG_NOINDEXCACHECOMPRESSION
411 outFile << out. str ();
412#else
413 ByteCompressor outCompr (outFile);
414 outCompr << out. str ();
415 outCompr. close ();
416#endif
417 outFile. close ();
418
419 return 0;
420} /* IndexCache::write */
421
422
423#endif // _CMGRAPHS_INDCACHE_H_
424
Writing and reading binary data (int, double) with bzip2 compression.
Utility procedures for writing and reading entire data structures with bzip2 compression,...
A simple wrapper for the bzip2 data compression to an output stream.
Definition: bytecompr.h:59
A simple wrapper for the bzip2 data decompression from an input stream.
Definition: bytecompr.h:295
The class that computes and returns properties of the Conley index.
Definition: conindex.h:86
Cached information on the Conley-Morse decompositions which contains information on computed Conley i...
Definition: indcache.h:66
std::vector< bool > emptyInv
The information on whether the invariant part of the given set has been proven to be empty.
Definition: indcache.h:90
std::vector< bool > skipped
The information on whether the computation of the given index was skipped due to the limit on the siz...
Definition: indcache.h:102
int write(const std::string &fileName, const theMorseDecompositionType &morseDec) const
Writes the cached information for the given Morse decomposition to a file.
Definition: indcache.h:367
~IndexCache()
The destructor of a cached information structure.
Definition: indcache.h:115
std::vector< bool > attractor
The information on whether the given Morse set is an attractor in the sense that its image is contain...
Definition: indcache.h:94
IndexCache(int nSets)
The constructor of an empty cached information structure for the given number of Morse sets.
Definition: indcache.h:108
int read(const std::string &fileName, theMorseDecompositionType &morseDec)
Reads the cached information from a file, matches it with the given Morse decomposition and sets the ...
Definition: indcache.h:120
std::vector< bool > wrongIndex
The information on whether the given index could not be computed because of a problem with isolation.
Definition: indcache.h:98
The Morse decoposition class.
Definition: morsedec.h:65
Choice of configuration settings.
Conley index computation routines.
Morse decompositions.
Customizable data types for the Conley-Morse graphs computation program.
Data types for the dynamical systems data structures.
chomp::homology::tCubeBase< spcCoord > spcCube
The type of a cube in the phase space.
Definition: typespace.h:55