1 /*
2 ================================================================================
3 PROJECT:
4
5 John Eddy's Genetic Algorithms (JEGA)
6
7 CONTENTS:
8
9 Implementation of class FlatFileInitializer.
10
11 NOTES:
12
13 See notes of FlatFileInitializer.hpp.
14
15 PROGRAMMERS:
16
17 John Eddy (jpeddy@sandia.gov) (JE)
18
19 ORGANIZATION:
20
21 Sandia National Laboratories
22
23 COPYRIGHT:
24
25 See the LICENSE file in the top level JEGA directory.
26
27 VERSION:
28
29 1.0.0
30
31 CHANGES:
32
33 Thu Jun 26 12:47:50 2003 - Original Version (JE)
34
35 ================================================================================
36 */
37
38
39
40
41 /*
42 ================================================================================
43 Document This File
44 ================================================================================
45 */
46 /** \file
47 * \brief Contains the implementation of the FlatFileInitializer class.
48 */
49
50
51
52 /*
53 ================================================================================
54 Includes
55 ================================================================================
56 */
57 // JEGAConfig.hpp should be the first include in all JEGA files.
58 #include <../Utilities/include/JEGAConfig.hpp>
59
60 #include <../Utilities/include/Logging.hpp>
61 #include <Initializers/FlatFileInitializer.hpp>
62 #include <../Utilities/include/DesignGroup.hpp>
63 #include <utilities/include/EDDY_DebugScope.hpp>
64 #include <Initializers/RandomUniqueInitializer.hpp>
65 #include <../Utilities/include/DesignFileReader.hpp>
66 #include <../Utilities/include/ParameterExtractor.hpp>
67
68
69
70
71
72 /*
73 ================================================================================
74 Namespace Using Directives
75 ================================================================================
76 */
77 using namespace std;
78 using namespace JEGA;
79 using namespace JEGA::Logging;
80 using namespace eddy::utilities;
81 using namespace JEGA::Utilities;
82
83
84
85
86
87
88
89
90 /*
91 ================================================================================
92 Begin Namespace
93 ================================================================================
94 */
95 namespace JEGA {
96 namespace Algorithms {
97
98
99
100
101
102
103
104
105 /*
106 ================================================================================
107 Static Member Data Definitions
108 ================================================================================
109 */
110 const std::string FlatFileInitializer::DEFAULT_DELIM;
111
112
113
114
115
116
117
118 /*
119 ================================================================================
120 Mutators
121 ================================================================================
122 */
123 void
SetFileNames(const JEGA::StringSet & fileNames)124 FlatFileInitializer::SetFileNames(
125 const JEGA::StringSet& fileNames
126 )
127 {
128 EDDY_FUNC_DEBUGSCOPE
129 this->_fileNames = fileNames;
130 JEGA_LOGGING_IF_ON(this->LogFilenames());
131 }
132
133 void
SetDelimiter(const std::string & delim)134 FlatFileInitializer::SetDelimiter(
135 const std::string& delim
136 )
137 {
138 EDDY_FUNC_DEBUGSCOPE
139
140 this->_delim = delim;
141
142 JEGALOG_II(this->GetLogger(), lverbose(), this,
143 text_entry(lverbose(),
144 this->GetName() + ": Delimiter now = " +
145 (this->_delim.empty() ? "<EMPTY STRING>" : this->_delim))
146 )
147
148 JEGAIFLOG_CF_II(this->_delim.empty(), this->GetLogger(), lverbose(), this,
149 text_entry(lverbose(), this->GetName() + ": Empty delimiter received. "
150 "As a result, the automatic delimiter discovery algorithm "
151 "will be employed."
152 )
153 )
154 }
155
156
157
158
159
160
161
162
163
164 /*
165 ================================================================================
166 Accessors
167 ================================================================================
168 */
169
170
171
172
173
174
175
176
177 /*
178 ================================================================================
179 Public Methods
180 ================================================================================
181 */
182
183 const string&
Name()184 FlatFileInitializer::Name(
185 )
186 {
187 EDDY_FUNC_DEBUGSCOPE
188 static const string ret("flat_file");
189 return ret;
190 }
191
192 const string&
Description()193 FlatFileInitializer::Description(
194 )
195 {
196 EDDY_FUNC_DEBUGSCOPE
197
198 static const string ret(
199 "This initializer attempts to read from a delimited file with the "
200 "following format:\n\n"
201 "dv0<delim>dv1...dvN[<delim>of0<delim>of1...ofM<delim>con0<delim>con1"
202 "...conK]\n\n"
203 "The delimiter can be any string. It will continue to read until "
204 "the end of the file. It will discard any configurations for which "
205 "it was unable to retrieve at least the number of design variables. "
206 "The objective and constraint entries are not required but if all are "
207 "present, they will be recorded and the Design will be tagged as "
208 "evaluated so that evaluators may choose not to re-evaluate them.\n\n"
209 "Setting the size for this initializer has the effect of requiring a "
210 "minimum number of Designs to create. If this minimum number has not "
211 "been created once the files are all read, the rest are created using "
212 "the random unique initializer."
213 );
214 return ret;
215 }
216
217 GeneticAlgorithmOperator*
Create(GeneticAlgorithm & algorithm)218 FlatFileInitializer::Create(
219 GeneticAlgorithm& algorithm
220 )
221 {
222 EDDY_FUNC_DEBUGSCOPE
223 return new FlatFileInitializer(algorithm);
224 }
225
226 bool
AddFileName(const string & fileName)227 FlatFileInitializer::AddFileName(
228 const string& fileName
229 )
230 {
231 EDDY_FUNC_DEBUGSCOPE
232 bool ret = this->_fileNames.insert(fileName).second;
233 JEGA_LOGGING_IF_ON(this->LogFilenames());
234 return ret;
235 }
236
237
238
239
240
241
242
243
244 /*
245 ================================================================================
246 Subclass Visible Methods
247 ================================================================================
248 */
249 JEGA::StringSet
ParseFileNames(const string & from)250 FlatFileInitializer::ParseFileNames(
251 const string& from
252 )
253 {
254 EDDY_FUNC_DEBUGSCOPE
255
256 JEGA::StringSet ret;
257
258 // if from is empty, there is nothing we can do.
259 if(from.empty()) return ret;
260
261 // place to store each filename as we encounter it
262 string fname;
263
264 // stores our current location in "from"
265 string::size_type strt = 0;
266
267 // extract the first value as a string.
268 fname.assign(this->GetNextField(from, "\t", strt));
269
270 // go for as long as we can get filenames.
271 while(!fname.empty())
272 {
273 // otherwise record the value
274 JEGA_LOGGING_IF_ON(bool inserted = ret.insert(fname).second;)
275 JEGA_LOGGING_IF_OFF(ret.insert(fname);)
276
277 JEGAIFLOG_CF_II(!inserted, this->GetLogger(), lquiet(), this,
278 text_entry(lquiet(), this->GetName() + ": Filename \"" + fname +
279 "\" found more than once. Repetitions ignored.")
280 )
281
282 // update the start to one past the most recent end
283 strt += fname.size() + 1;
284
285 // extract the next value as a string.
286 fname.assign(this->GetNextField(from, strt));
287 }
288
289 return ret;
290 }
291
292 JEGA::StringSet
ParseFileNames(const JEGA::StringSet & from)293 FlatFileInitializer::ParseFileNames(
294 const JEGA::StringSet& from
295 )
296 {
297 EDDY_FUNC_DEBUGSCOPE
298 StringSet ret;
299
300 for(StringSet::const_iterator it(from.begin()); it!=from.end(); ++it)
301 {
302 StringSet curr(this->ParseFileNames(*it));
303 ret.insert(curr.begin(), curr.end());
304 }
305
306 return ret;
307 }
308
309 string
GetNextField(const string & from,const string & delim,const string::size_type off)310 FlatFileInitializer::GetNextField(
311 const string& from,
312 const string& delim,
313 const string::size_type off
314 )
315 {
316 EDDY_FUNC_DEBUGSCOPE
317
318 // Check for trivial abort condition.
319 if(off >= from.size()) return string();
320
321 // Find the next occurrence of the delimiter.
322 string::size_type end = from.find(delim, off);
323
324 // return the substring consisting of everything from
325 // the offset to the delimiter.
326 return from.substr(off, end-off);
327 }
328
329 string
GetNextField(const string & from,const string::size_type off) const330 FlatFileInitializer::GetNextField(
331 const string& from,
332 const string::size_type off
333 ) const
334 {
335 EDDY_FUNC_DEBUGSCOPE
336 return this->GetNextField(from, this->_delim, off);
337 }
338
339
340 /*
341 ================================================================================
342 Subclass Overridable Methods
343 ================================================================================
344 */
345
346 string
GetName() const347 FlatFileInitializer::GetName(
348 ) const
349 {
350 EDDY_FUNC_DEBUGSCOPE
351 return FlatFileInitializer::Name();
352 }
353
354 string
GetDescription() const355 FlatFileInitializer::GetDescription(
356 ) const
357 {
358 EDDY_FUNC_DEBUGSCOPE
359 return FlatFileInitializer::Description();
360 }
361
362 GeneticAlgorithmOperator*
Clone(GeneticAlgorithm & algorithm) const363 FlatFileInitializer::Clone(
364 GeneticAlgorithm& algorithm
365 ) const
366 {
367 EDDY_FUNC_DEBUGSCOPE
368 return new FlatFileInitializer(*this, algorithm);
369 }
370
371
372 void
Initialize(DesignGroup & into)373 FlatFileInitializer::Initialize(
374 DesignGroup& into
375 )
376 {
377 EDDY_FUNC_DEBUGSCOPE
378
379 JEGALOG_II(this->GetLogger(), ldebug(), this,
380 text_entry(ldebug(), this->GetName() + ": Performing initialization.")
381 )
382
383 // get the target for the designs we create.
384 DesignTarget& target = into.GetDesignTarget();
385
386 // find out the requested minimum number of Designs
387 const std::size_t minsize = this->GetSize();
388
389 JEGA_LOGGING_IF_ON(const std::size_t prevSize = into.GetSize();)
390
391 // read in each file one at a time
392 for(StringSet::const_iterator it(this->_fileNames.begin());
393 it!=this->_fileNames.end(); ++it)
394 {
395 DesignFileReader::Result readResults(
396 DesignFileReader::ReadFlatFile(*it, this->_delim, target)
397 );
398
399 if(readResults.GetErrorFlag())
400 {
401 JEGALOG_II(this->GetLogger(), lquiet(), this,
402 text_entry(lquiet(), this->GetName() + ": Encountered fatal "
403 "error while attempting to read file \"" + *it + "\". "
404 "Make sure the file exists and is a JEGA Design flat file."
405 )
406 )
407 continue;
408 }
409 else into.AbsorbDesigns(readResults.GetDesigns());
410
411 // indicate what happened
412 JEGALOG_II(this->GetLogger(), lverbose(), this,
413 text_entry(
414 lverbose(), this->GetName() + ": \n" +
415 readResults.GetResultsString()
416 )
417 )
418
419 }
420
421 JEGAIFLOG_CF_II(into.IsEmpty(), this->GetLogger(), lquiet(), this,
422 text_entry(lquiet(), this->GetName() + ": No designs were read from "
423 "initialization files. All initial designs will be "
424 "generated by the random unique initializer.")
425 )
426
427 // now we have to make sure that we have enough according to the
428 // requested minimum size.
429 if(into.GetSize() < minsize)
430 {
431 // we will use the random unique initializer to fill
432 // in the rest.
433
434 JEGALOG_II(this->GetLogger(), lverbose(), this,
435 text_entry(lverbose(), this->GetName() + ": The desired number of "
436 "designs were not found in the supplied file(s). Using the "
437 "random unique initializer to generate the remaining designs."
438 )
439 )
440
441 RandomUniqueInitializer subiniter(this->GetAlgorithm());
442 subiniter.SetSize(minsize - into.GetSize());
443 subiniter.Initialize(into);
444 }
445
446 JEGAIFLOG_CF_II_F(into.IsEmpty(), this->GetLogger(), this,
447 text_entry(lfatal(), this->GetName() + ": Unable to generate any "
448 "initial designs even with the help of the random unique "
449 "initializer.")
450 )
451
452 JEGAIFLOG_CF_II_F(into.GetSize() < 2, this->GetLogger(), this,
453 text_entry(lfatal(), this->GetName() + ": Unable to generate minimum "
454 "of 2 initial designs even with the help of the random "
455 "unique initializer.")
456 )
457
458 JEGALOG_II(this->GetLogger(), lverbose(), this,
459 ostream_entry(lverbose(), this->GetName() + ": ")
460 << (into.GetSize() - prevSize)
461 << " total designs read or created."
462 )
463
464 JEGALOG_II(this->GetLogger(), lquiet(), this,
465 ostream_entry(lquiet(),
466 this->GetName() + ": Final initial population size: ")
467 << into.GetSize() << "."
468 )
469
470 // Set the size to the number of successful reads.
471 this->SetSize(into.GetSize());
472 }
473
474 bool
PollForParameters(const JEGA::Utilities::ParameterDatabase & db)475 FlatFileInitializer::PollForParameters(
476 const JEGA::Utilities::ParameterDatabase& db
477 )
478 {
479 EDDY_FUNC_DEBUGSCOPE
480
481 // Get the delimiter
482 bool success = ParameterExtractor::GetStringFromDB(
483 db, "method.jega.initializer_delimiter", _delim
484 );
485
486 JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
487 text_entry(lverbose(), this->GetName() + ": The field delimiter was "
488 "not found in the parameter database. Using the current " +
489 "delimiter " +
490 (this->_delim.empty() ? "<EMPTY STRING>" : this->_delim) + ".")
491 )
492
493 this->SetDelimiter(this->_delim);
494
495 // The user may have given us a single filename or multiple or both! First
496 // extract the single name if present.
497 string tstr;
498 success = ParameterExtractor::GetStringFromDB(db, "method.flat_file", tstr);
499
500 // Create a temporary set and initialize it with our filename. Don't parse
501 // it yet. That will happen in one step when we have collected all our
502 // filenames.
503 JEGA::StringSet fnames;
504 if(success) fnames.insert(tstr);
505
506 // Now get the multiple names and merge them with our existing name.
507 JEGA::StringVector sfnames;
508 success = ParameterExtractor::GetStringVectorFromDB(
509 db, "method.flat_files", sfnames
510 );
511
512 if(success) fnames.insert(sfnames.begin(), sfnames.end());
513
514 // Now parse all the items in fnames and make that our new list of files.
515 fnames = this->ParseFileNames(fnames);
516
517 JEGAIFLOG_CF_II(fnames.empty(), this->GetLogger(), lquiet(), this,
518 text_entry(lquiet(), this->GetName() + ": No filenames obtained for "
519 "initialization.")
520 )
521
522 // Even if no filenames have been supplied, continue. The initialization
523 // will just use the random unique for all of them.
524 this->SetFileNames(fnames);
525
526 return this->GeneticAlgorithmInitializer::PollForParameters(db);
527 }
528
529
530
531
532
533
534 /*
535 ================================================================================
536 Private Methods
537 ================================================================================
538 */
539 void
LogFilenames() const540 FlatFileInitializer::LogFilenames(
541 ) const
542 {
543 #ifdef JEGA_LOGGING_ON
544 if(this->GetLogger().Gate().will_log(this, lverbose()))
545 {
546 string allFiles;
547
548 StringSet::const_iterator e(this->_fileNames.end());
549 if(!this->_fileNames.empty()) --e;
550 for(StringSet::const_iterator it(this->_fileNames.begin()); it!=e; ++it)
551 allFiles.append(*it + ",");
552
553 if(!this->_fileNames.empty()) allFiles.append(*e);
554
555 JEGALOG_II(this->GetLogger(), lverbose(), this,
556 text_entry(lverbose(), this->GetName() +
557 ": Initialization file(s) now = " + allFiles)
558 )
559 }
560 #endif
561
562 }
563
564
565
566
567
568
569
570
571 /*
572 ================================================================================
573 Structors
574 ================================================================================
575 */
576
FlatFileInitializer(GeneticAlgorithm & algorithm)577 FlatFileInitializer::FlatFileInitializer(
578 GeneticAlgorithm& algorithm
579 ) :
580 GeneticAlgorithmInitializer(algorithm),
581 _delim(DEFAULT_DELIM),
582 _fileNames()
583 {
584 EDDY_FUNC_DEBUGSCOPE
585
586 // override the default requested initial size to zero.
587 // For this initializer, this is the min size. A value of
588 // 0 will result in using only the Designs found in the file.
589 this->SetSize(0);
590 }
591
FlatFileInitializer(const FlatFileInitializer & copy)592 FlatFileInitializer::FlatFileInitializer(
593 const FlatFileInitializer& copy
594 ) :
595 GeneticAlgorithmInitializer(copy),
596 _delim(copy._delim),
597 _fileNames(copy._fileNames)
598 {
599 EDDY_FUNC_DEBUGSCOPE
600 }
601
FlatFileInitializer(const FlatFileInitializer & copy,GeneticAlgorithm & algorithm)602 FlatFileInitializer::FlatFileInitializer(
603 const FlatFileInitializer& copy,
604 GeneticAlgorithm& algorithm
605 ) :
606 GeneticAlgorithmInitializer(copy, algorithm),
607 _delim(copy._delim),
608 _fileNames(copy._fileNames)
609 {
610 EDDY_FUNC_DEBUGSCOPE
611 }
612
613
614
615
616
617
618
619
620 /*
621 ================================================================================
622 End Namespace
623 ================================================================================
624 */
625 } // namespace Algorithms
626 } // namespace JEGA
627