$darkmode
DENOPTIM
EvolutionaryAlgorithm.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2019 Vishwesh Venkatraman <vishwesh.venkatraman@ntnu.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.ga;
20
21import java.io.File;
22import java.util.ArrayList;
23import java.util.Arrays;
24import java.util.Collections;
25import java.util.HashMap;
26import java.util.HashSet;
27import java.util.List;
28import java.util.Map;
29import java.util.Set;
30import java.util.concurrent.ArrayBlockingQueue;
31import java.util.concurrent.Future;
32import java.util.concurrent.RejectedExecutionHandler;
33import java.util.concurrent.ThreadPoolExecutor;
34import java.util.concurrent.TimeUnit;
35import java.util.logging.Level;
36import java.util.logging.Logger;
37
38import org.apache.commons.lang3.time.StopWatch;
39import org.openscience.cdk.io.iterator.IteratingSMILESReader;
40
41import denoptim.exception.DENOPTIMException;
42import denoptim.exception.ExceptionUtils;
43import denoptim.fitness.FitnessParameters;
44import denoptim.ga.EAUtils.CandidateSource;
45import denoptim.graph.Candidate;
46import denoptim.io.IteratingAtomContainerReader;
47import denoptim.logging.CounterID;
48import denoptim.logging.Monitor;
49import denoptim.programs.RunTimeParameters.ParametersType;
50import denoptim.programs.denovo.GAParameters;
51import denoptim.programs.fragmenter.FragmenterParameters;
52import denoptim.task.FitnessTask;
53import denoptim.task.Task;
54import denoptim.task.TasksBatchManager;
55import denoptim.utils.SizeControlledSet;
56
93{
98
103
107 private boolean stopped = false;
108
113 private Set<String> candidatesToRemove = new HashSet<String>();
114
120 private List<String> candidatesToAdd = new ArrayList<String>();
121
125 private boolean isAsync = true;
126
131 private Map<FitnessTask,Future<Object>> futures;
132
137 private List<FitnessTask> submitted;
138
142 private ThreadPoolExecutor tpe;
143
148
153 private Throwable ex;
154
159
163 private Logger logger = null;
164
165 private final String NL = System.getProperty("line.separator");
166
167//------------------------------------------------------------------------------
168
171 {
172 this.settings = settings;
173 this.logger = settings.getLogger();
174 this.cmdListener = cmdListener;
175
176 // There is currently nothing to initialize for the synchronous scheme
178 {
179 isAsync = false;
180 tbm = new TasksBatchManager();
181
182 } else {
183 isAsync = true;
184 futures = new HashMap<FitnessTask,Future<Object>>();
185 submitted = new ArrayList<>();
186
187 tpe = new ThreadPoolExecutor(settings.getNumberOfCPU(),
189 TimeUnit.MILLISECONDS,
190 new ArrayBlockingQueue<Runnable>(1));
191
192 Runtime.getRuntime().addShutdownHook(new Thread()
193 {
194 @Override
195 public void run()
196 {
197 tpe.shutdown(); // Disable new tasks from being submitted
198 try
199 {
200 // Wait a while for existing tasks to terminate
201 if (!tpe.awaitTermination(30, TimeUnit.SECONDS))
202 {
203 tpe.shutdownNow(); //Cancel running tasks
204 }
205 if (!tpe.awaitTermination(60, TimeUnit.SECONDS))
206 {
207 // pool didn't terminate after the second try
208 }
209 }
210 catch (InterruptedException ie)
211 {
212 cleanupAsync();
213 // (Re-)Cancel if current thread also interrupted
214 tpe.shutdownNow();
215 // Preserve interrupt status
216 Thread.currentThread().interrupt();
217 }
218 }
219 });
220
221 // by default the ThreadPoolExecutor will throw an exception
222 tpe.setRejectedExecutionHandler(new RejectedExecutionHandler()
223 {
224 @Override
225 public void rejectedExecution(Runnable r,
226 ThreadPoolExecutor executor)
227 {
228 try
229 {
230 // this will block if the queue is full
231 executor.getQueue().put(r);
232 }
233 catch (InterruptedException ex)
234 {
235 //nothing, really
236 }
237 }
238 });
239 }
240
244 }
245
246//------------------------------------------------------------------------------
247
248 public void run() throws DENOPTIMException
249 {
251
252 StopWatch watch = new StopWatch();
253 watch.start();
254 if (isAsync)
255 {
256 tpe.prestartAllCoreThreads();
257 }
258 Monitor mnt = new Monitor();
260
261 // Create initial population of candidates
263 Population population;
264 try
265 {
267 } catch (Exception e)
268 {
269 throw new DENOPTIMException("Unable to import initial population.",
270 e);
271 }
272 initializePopulation(population);
273
274 boolean writeCandsOnDisk = ((FitnessParameters) settings.getParameters(
275 ParametersType.FIT_PARAMS)).writeCandidatesOnDisk();
278 settings, writeCandsOnDisk);
279
280 // Ensure that there is some variability in fitness values
281 double sdev = EAUtils.getPopulationSD(population);
282 if (sdev < settings.getMinFitnessSD())
283 {
284 String msg = "Fitness values have negligible standard deviation "
285 + "(STDDEV=" + String.format("%.6f", sdev) + "). "
286 + "Abbandoning evolutionary algorithm.";
287 logger.log(Level.SEVERE, msg);
288 population.trim(0);
289 return;
290 }
291
292 // Start evolution cycles, i.e., generations
293 int numStag = 0, genId = 1;
294 while (genId <= settings.getNumberOfGenerations())
295 {
296 logger.log(Level.INFO,"Starting Generation {0}"
297 + NL, genId);
298
299 String txt = "No change";
300 try
301 {
302 if (!evolvePopulation(population, genId))
303 {
304 numStag++;
305 }
306 else
307 {
308 numStag = 0;
309 txt = "New members introduced";
310 }
311 } catch (DENOPTIMException e)
312 {
313 logger.log(Level.SEVERE, "Exception while running evolutionary"
314 + "algorithm. Details: " + NL
316 throw e;
317 }
318
319 logger.log(Level.INFO,txt + " in Generation {0}"
320 + NL, genId);
323 settings, writeCandsOnDisk);
324
325 if (stopped)
326 {
327 logger.log(Level.SEVERE,
328 "EA stopped while working on generation {0}. " + NL
329 + "Reporting data for incomplete generation {0}."
330 + NL,genId);
331 break;
332 } else {
333 logger.log(Level.INFO,
334 "Generation {0}" + " completed" + NL
335 + "----------------------------------------"
336 + "----------------------------------------"
337 + NL, genId);
338 }
339
341 {
342 logger.log(Level.WARNING,
343 "No change in population over {0} iterations. "
344 + "Stopping EA." + NL, numStag);
345 break;
346 }
347
348 genId++;
349 }
350
351 if (isAsync)
352 {
353 tpe.shutdown();
354 try
355 {
356 // wait a bit for pending tasks to finish
357 while (!tpe.awaitTermination(5, TimeUnit.SECONDS))
358 {
359 // do nothing
360 }
361 }
362 catch (InterruptedException ex)
363 {
364 //Do nothing
365 }
366 tpe.shutdown();
367 }
368
369 // Sort the population and trim it to desired size
370 Collections.sort(population, Collections.reverseOrder());
372 {
373 population.trim(settings.getPopulationSize());
374 }
375
376 // And write final results
378
379 // Termination
380 population.trim(0);
381 watch.stop();
382 logger.log(Level.INFO, "Overall time: {0}." + NL,
383 watch.toString());
384
385 if (stopped)
386 {
387 logger.info("DENOPTIM EA run stopped." + NL);
388 } else {
389 logger.info("DENOPTIM EA run completed." + NL);
390 }
391 }
392
393//------------------------------------------------------------------------------
394
402 private void initializePopulation(Population population)
403 throws DENOPTIMException
404 {
405 // Deal with existing initial population members
406 synchronized (population)
407 {
408 if (stopped)
409 {
410 return;
411 }
412
413 // Keep only the best candidates if there are too many.
414 Collections.sort(population, Collections.reverseOrder());
415 if (settings.getReplacementStrategy() == 1 &&
416 population.size() > settings.getPopulationSize())
417 {
418 population.trim(settings.getPopulationSize());
419 }
420 }
421 // NB: pop size cannot be > because it has been just trimmed
422 if (population.size() == settings.getPopulationSize())
423 {
424 return;
425 }
426
427 Monitor mnt = new Monitor("MonitorGen",0,settings.getMonitorFile(),
430
431 // Screen molecules (these can be very many!)
433 {
434 IteratingAtomContainerReader iterMolsToFragment = null;
435 try
436 {
437 iterMolsToFragment = new IteratingAtomContainerReader(new File(
439 if (iterMolsToFragment.getIteratorType().equals(
440 IteratingSMILESReader.class))
441 {
444 {
445 frgParams = (FragmenterParameters)
448 }
449 frgParams.setWorkingIn3D(false);
450 }
451 } catch (Exception e1)
452 {
453 throw new DENOPTIMException("Could not set reader on file ''"
455 }
456
457 // This is very similar to the standard population initialization
458 // async loop, but it allows to screen many more candidates because
459 // it keeps only best N, where N is the size of the population.
460 // Yet, there is plenty of repeated code, which is sub-optimal.
461 int i=0;
462 List<Task> batchOfSyncParallelTasks = new ArrayList<>();
463 try
464 {
465 while (iterMolsToFragment.hasNext())
466 {
467 i++;
468
469 if (stopped)
470 {
471 break;
472 }
473
474 if (checkForException())
475 {
476 stopRun();
477 throw new DENOPTIMException("Errors found during sub "
478 + "tasks execution.", ex);
479 }
480
481 Candidate candidate =
483 iterMolsToFragment.next(), mnt, settings, i);
484
485 // NB: here we request to keep only the best candidates
486 // so that the tmp population does not become too large
487 // before being trimmed.
488 i = processInitialPopCandidate(candidate, population, mnt,
489 batchOfSyncParallelTasks, i, true, true);
490 }
491 // We still need to submit the possibly partially-filled last batch
492 if (batchOfSyncParallelTasks.size()>0)
493 submitSyncParallelBatch(batchOfSyncParallelTasks);
494 } catch (DENOPTIMException dex)
495 {
496 if (isAsync)
497 {
498 cleanupAsync();
499 tpe.shutdown();
500 }
501 throw dex;
502 }
503 catch (Exception ex)
504 {
505 if (isAsync)
506 {
507 cleanupAsync();
508 tpe.shutdown();
509 }
510 ex.printStackTrace();
511 throw new DENOPTIMException(ex);
512 }
513 }
514
515 // Loop for creation of candidates until we have created enough new valid
516 // candidates or we have reached the max number of attempts.
517 // WARNING: careful about the duplication of code in this loop and in
518 // the one above (with iterMolsToFragment)
519 int i=0;
520 List<Task> tasks = new ArrayList<>();
521 try
522 {
523 while (i < settings.getPopulationSize() *
525 {
526 i++;
527
528 if (stopped)
529 {
530 break;
531 }
532
533 if (checkForException())
534 {
535 stopRun();
536 throw new DENOPTIMException("Errors found during sub tasks "
537 + "execution.", ex);
538 }
539
540 synchronized (population)
541 {
542 if (population.size() >= settings.getPopulationSize())
543 break;
544 }
545
547 settings);
548
549 i = processInitialPopCandidate(candidate, population, mnt,
550 tasks, i, false, false);
551 }
552 } catch (DENOPTIMException dex)
553 {
554 if (isAsync)
555 {
556 cleanupAsync();
557 tpe.shutdown();
558 }
559 throw dex;
560 }
561 catch (Exception ex)
562 {
563 if (isAsync)
564 {
565 cleanupAsync();
566 tpe.shutdown();
567 }
568 ex.printStackTrace();
569 throw new DENOPTIMException(ex);
570 }
571
572 mnt.printSummary();
573
574 if (i >= (settings.getPopulationSize() *
576 {
577 if (isAsync)
578 {
580 stopRun();
581 }
582 logger.log(Level.SEVERE,
583 "Unable to initialize population in {0} attempts."+NL, i);
584
585 throw new DENOPTIMException("Unable to initialize population in "
586 + i + " attempts (Population size: " + population.size()
587 + ", tasks batch size: " + tasks.size() + ").");
588 }
589
590 synchronized (population)
591 {
592 // NB: this does not remove any item from the list
593 population.trimToSize();
594 Collections.sort(population, Collections.reverseOrder());
595 }
596 }
597
598//------------------------------------------------------------------------------
599
616 private int processInitialPopCandidate(Candidate candidate,
617 Population population, Monitor mnt,
618 List<Task> batchOfSyncParallelTasks, int attemptsToFillBatch,
619 boolean replaceWorstPopMember, boolean candidatesOverflow)
620 throws DENOPTIMException
621 {
622 if (candidate == null)
623 return attemptsToFillBatch;
624
625 candidate.setGeneration(0);
626
628 ParametersType.FIT_PARAMS)).checkPreFitnessUID())
629 {
630 try
631 {
632 if (!scs.addNewUniqueEntry(candidate.getUID()))
633 {
634 mnt.increase(CounterID.DUPLICATEPREFITNESS);
635 return attemptsToFillBatch;
636 }
637 } catch (Exception e) {
639 return attemptsToFillBatch;
640 }
641 }
642
644 settings,
645 candidate,
646 null,
648 population, mnt, settings.getUIDFileOut(),
649 replaceWorstPopMember);
650
651 // Submission is dependent on the parallelization scheme
652 if (isAsync)
653 {
654 submitted.add(task);
655 futures.put(task, tpe.submit(task));
656 // We keep some memory but of previous tasks, but must
657 // avoid memory leak due to storage of too many references
658 // to submitted tasks.
659 if (submitted.size() > 2*settings.getNumberOfCPU())
660 {
662 }
663 } else {
664 batchOfSyncParallelTasks.add(task);
665 boolean submitBatch = false;
666 if (!candidatesOverflow)
667 {
668 submitBatch = batchOfSyncParallelTasks.size() >= Math.abs(
669 population.size() - settings.getPopulationSize())
670 ||
671 //This to avoid the fixed batch size to block the
672 //generation of new candidates for too long
673 attemptsToFillBatch >= (0.1 * settings.getPopulationSize() *
675 } else {
676 submitBatch = batchOfSyncParallelTasks.size()
678 }
679 if (submitBatch)
680 {
681 // Now we have as many tasks as are needed to fill up the
682 // population or the batch.
683 // Therefore we can run the execution service.
684 // TasksBatchManager takes the collection of tasks and runs
685 // them in batches of N according to the GA settings.
686 submitSyncParallelBatch(batchOfSyncParallelTasks);
687 } else {
688 attemptsToFillBatch = 0;
689 }
690 }
691 return attemptsToFillBatch;
692 }
693
694//------------------------------------------------------------------------------
695
696 private void submitSyncParallelBatch(List<Task> batchOfSyncParallelTasks)
697 throws DENOPTIMException
698 {
699 tbm.executeTasks(batchOfSyncParallelTasks,
701 batchOfSyncParallelTasks.clear();
702 }
703
704//------------------------------------------------------------------------------
705
714 private boolean evolvePopulation(Population population,
715 int genId) throws DENOPTIMException
716 {
718
719 // Take a snapshot of the initial population members. This to exclude
720 // that offsprings of this generation become parents in this generation.
721 List<Candidate> eligibleParents = new ArrayList<Candidate>();
722 int populationVersion = -1;
723 int newPopSize = -1;
724 synchronized (population)
725 {
726 for (Candidate c : population)
727 {
728 eligibleParents.add(c);
729 }
731 {
732 newPopSize = settings.getNumberOfChildren()
733 + eligibleParents.size();
734 } else {
735 population.clear();
736 newPopSize = settings.getPopulationSize();
737 }
738 populationVersion = population.getVersionID();
739 }
740
741 int i=0;
742 List<Task> syncronisedTasks = new ArrayList<>();
743 Monitor mnt = new Monitor("MonitorGen", genId,
746 try
747 {
748 while (i < settings.getPopulationSize() *
750 {
751 i++;
752
753 if (stopped)
754 {
755 break;
756 }
757
758 if (checkForException())
759 {
760 stopRun();
761 throw new DENOPTIMException("Errors found during sub-tasks "
762 + "execution.", ex);
763 }
764
765 synchronized (population)
766 {
767 synchronized (candidatesToRemove)
768 {
769 if (candidatesToRemove.size()>0)
770 {
771 for (String id : candidatesToRemove)
772 {
773 Candidate c = population.getCandidateNamed(id);
774 if (c != null)
775 {
776 population.remove(c);
777 eligibleParents.remove(c);
778 }
779 }
780 candidatesToRemove.clear();
781 }
782 }
783 }
784
785 synchronized (population)
786 {
787 if (population.size() >= newPopSize)
788 break;
789 }
790
791 File srcOfCandidate = null;
792 List<Candidate> candidatesToEvaluate = new ArrayList<>();
793
794 synchronized (candidatesToAdd)
795 {
796 if (candidatesToAdd.size()>0)
797 {
798 srcOfCandidate = new File(candidatesToAdd.get(0));
799 candidatesToAdd.remove(0);
801 srcOfCandidate, mnt, settings);
802 if (candidate == null)
803 continue;
804 else
805 candidatesToEvaluate.add(candidate);
806 }
807 }
808
809 if (candidatesToEvaluate.size()==0)
810 {
812 {
813 candidatesToEvaluate.addAll(makeOffspringB(
814 eligibleParents, population, mnt));
815 } else {
816 candidatesToEvaluate.addAll(makeOffspringA(
817 eligibleParents, population, mnt));
818 }
819 }
820 if (candidatesToEvaluate.size()==0)
821 continue;
822
823 // NB: for now we assume there can be up to two siblings
824 for (int iSibling=0; iSibling<candidatesToEvaluate.size(); iSibling++)
825 {
826 Candidate candidate = candidatesToEvaluate.get(iSibling);
827 int jSibling = 1;
828 if (iSibling==1)
829 jSibling = 0;
830
831 Candidate sibling = null;
832 if (candidatesToEvaluate.size()>1)
833 sibling = candidatesToEvaluate.get(jSibling);
834
835 candidate.setGeneration(genId);
836
838 ParametersType.FIT_PARAMS)).checkPreFitnessUID())
839 {
840 try
841 {
842 if (!scs.addNewUniqueEntry(candidate.getUID()))
843 {
845 continue;
846 }
847 } catch (Exception e) {
848 mnt.increase(
850 continue;
851 }
852 }
853
855 settings,
856 candidate,
857 sibling,
859 population, mnt, settings.getUIDFileOut(), false);
860
861 if (isAsync)
862 {
863 submitted.add(task);
864 futures.put(task, tpe.submit(task));
865 // We keep some memory of previous tasks, but must
866 // avoid memory leak due to storage of too many references
867 // to submitted tasks.
868 if (submitted.size() > 2*settings.getNumberOfCPU())
869 {
871 }
872 } else {
873 syncronisedTasks.add(task);
874 if (syncronisedTasks.size()
875 >= Math.abs(population.size() - newPopSize)
876 ||
877 //This to avoid the fixed batch size to block the
878 //generation of new candidates for too long
879 i >= (0.1 * settings.getPopulationSize() *
881 {
882 // Now we have as many tasks as are needed to fill up
883 // the population, or we got sick to wait.
884 // TasksBatchManager takes the collection of tasks and
885 // runs them in batches of N, where N is given by the
886 // second argument.
887 submitSyncParallelBatch(syncronisedTasks);
888 }
889 }
890 }
891 }
892 }
893 catch (DENOPTIMException dex)
894 {
895 if (isAsync)
896 {
897 cleanupAsync();
898 tpe.shutdown();
899 }
900 dex.printStackTrace();
901 throw dex;
902 }
903 catch (Exception ex)
904 {
905 if (isAsync)
906 {
907 cleanupAsync();
908 tpe.shutdown();
909 }
910 ex.printStackTrace();
911 throw new DENOPTIMException(ex);
912 }
913
914 mnt.printSummary();
915
916 if (i >= (settings.getPopulationSize() *
918 {
919 if (isAsync)
920 {
922 stopRun();
923 }
924 logger.log(Level.WARNING,
925 "Reached maximum number of attempts (" + i + ") to "
926 + "generate new candidates in generation " + genId + "."
927 + NL);
928 }
929
930 // sort the population and trim it to size
931 synchronized (population)
932 {
933 Collections.sort(population, Collections.reverseOrder());
935 {
936 population.trim(settings.getPopulationSize());
937 }
938 }
939
940 eligibleParents = null;
941 syncronisedTasks.clear();
942
943 // Check if the population has changed
944 int newPopulationVersion = -1;
945 synchronized (population)
946 {
947 newPopulationVersion = population.getVersionID();
948 }
949
950 return populationVersion != newPopulationVersion;
951 }
952
953//------------------------------------------------------------------------------
954
974 @SuppressWarnings("incomplete-switch")
975 private List<Candidate> makeOffspringA(List<Candidate> eligibleParents,
976 Population population, Monitor mnt) throws DENOPTIMException
977 {
979
980 List<Candidate> candidates = new ArrayList<Candidate>();
981 switch (src)
982 {
983 // MANUAL is not a valid choice here
984 case CROSSOVER:
985 {
986 candidates.addAll(EAUtils.buildCandidatesByXOver(
987 eligibleParents, population, mnt, settings));
988 break;
989 }
990
991 case MUTATION:
992 {
994 eligibleParents, mnt, settings);
995 if (candidate!=null)
996 candidates.add(candidate);
997 break;
998 }
999
1000 case CONSTRUCTION:
1001 {
1003 settings);
1004 if (candidate!=null)
1005 candidates.add(candidate);
1006 break;
1007 }
1008 }
1009 return candidates;
1010 }
1011
1012//------------------------------------------------------------------------------
1013
1035 @SuppressWarnings("incomplete-switch")
1036 private List<Candidate> makeOffspringB(List<Candidate> eligibleParents,
1037 Population population, Monitor mnt) throws DENOPTIMException
1038 {
1044
1045 List<Candidate> candidates = new ArrayList<Candidate>();
1046 switch (src)
1047 {
1048 case CROSSOVER:
1049 {
1050 candidates.addAll(EAUtils.buildCandidatesByXOver(
1051 eligibleParents, population, mnt, settings));
1052 break;
1053 }
1054
1055 case MUTATION:
1056 {
1057 List<Candidate> parents = EAUtils.buildCandidatesByXOver(
1058 eligibleParents, population, mnt, settings);
1059 for (Candidate parent : parents)
1060 {
1061 String provenanceMsg = parent.getGraph().getLocalMsg();
1063 Arrays.asList(parent), mnt, settings);
1064 if (candidate!=null)
1065 {
1066 candidate.getGraph().setLocalMsg("MutationOn" +
1067 provenanceMsg);
1068 candidates.add(candidate);
1069 }
1070 }
1071 break;
1072 }
1073
1074 case CONSTRUCTION:
1075 {
1077 settings);
1078 if (candidate!=null)
1079 candidates.add(candidate);
1080 break;
1081 }
1082 }
1083 return candidates;
1084 }
1085
1086//------------------------------------------------------------------------------
1087
1088 public void stopRun()
1089 {
1090 if (isAsync)
1091 {
1092 cleanupAsync();
1093 tpe.shutdown();
1094 }
1095 stopped = true;
1096 }
1097
1098//------------------------------------------------------------------------------
1099
1103 private void cleanupAsync()
1104 {
1105 for (FitnessTask tsk: submitted)
1106 {
1107 tsk.stopTask();
1108 }
1109 for (FitnessTask tsk : futures.keySet())
1110 {
1111 futures.get(tsk).cancel(true);
1112 }
1113 futures.clear();
1114 submitted.clear();
1115 tpe.getQueue().clear();
1116 }
1117
1118//------------------------------------------------------------------------------
1119
1123 private void cleanupCompleted()
1124 {
1125 List<FitnessTask> completed = new ArrayList<FitnessTask>();
1126
1127 for (FitnessTask t : submitted)
1128 {
1129 if (t.isCompleted())
1130 completed.add(t);
1131 }
1132
1133 for (FitnessTask t : completed)
1134 {
1135 submitted.remove(t);
1136 futures.get(t).cancel(true);
1137 futures.remove(t);
1138 }
1139 }
1140
1141//------------------------------------------------------------------------------
1142
1143 private boolean checkForException()
1144 {
1145 boolean foundExceptions = false;
1146 if (isAsync)
1147 {
1148 for (FitnessTask tsk : submitted)
1149 {
1150 boolean interrupt = false;
1151 synchronized (tsk.lock)
1152 {
1153 if (tsk.foundException())
1154 {
1155 foundExceptions = true;
1156 logger.log(Level.SEVERE, "problems in "
1157 + tsk.toString() + ". ErrorMessage: '"
1158 + tsk.getErrorMessage() + "'. ExceptionInTask: "
1159 + tsk.getException());
1160 ex = tsk.getException().getCause();
1161 interrupt = true;
1162 }
1163 }
1164 if (interrupt)
1165 break;
1166 }
1167 } else {
1168 // We don't really check of exceptions for synchronous scheme
1169 // because the executor service will detect the exception and stop
1170 // the experiment.
1171 }
1172 return foundExceptions;
1173 }
1174
1175//------------------------------------------------------------------------------
1176
1180 public void removeCandidates(Set<String> candID)
1181 {
1182 synchronized (candidatesToRemove)
1183 {
1184 candidatesToRemove.addAll(candID);
1185 }
1186 }
1187
1188//------------------------------------------------------------------------------
1189
1193 public void addCandidates(Set<String> pathNames)
1194 {
1195 synchronized (candidatesToAdd)
1196 {
1197 for (String pathName : pathNames)
1198 {
1199 if (!candidatesToAdd.contains(pathName))
1200 candidatesToAdd.add(pathName);
1201 }
1202 }
1203 }
1204
1205//------------------------------------------------------------------------------
1206
1207}
static String getStackTraceAsString(Throwable t)
Prints the stack trace of an exception into a string.
Settings defining the calculation of fitness.
Helper methods for the genetic algorithm.
Definition: EAUtils.java:107
static void outputFinalResults(Population popln, GAParameters settings)
Saves the final results to disk.
Definition: EAUtils.java:1634
static CandidateSource pickNewCandidateGenerationMode(double xoverWeight, double mutWeight, double newWeight, Randomizer randomizer)
Takes a decision on which CandidateSource method to use for generating a new Candidate.
Definition: EAUtils.java:263
static Candidate readCandidateFromFile(File srcFile, Monitor mnt, GAParameters settings)
Definition: EAUtils.java:769
static List< Candidate > buildCandidatesByXOver(List< Candidate > eligibleParents, Population population, Monitor mnt, GAParameters settings)
Generates a pair of new offspring by performing a crossover operation.
Definition: EAUtils.java:293
static CandidateSource chooseGenerationMethod(GAParameters settings)
Choose one of the methods to make new Candidates.
Definition: EAUtils.java:207
static Candidate buildCandidateByMutation(List< Candidate > eligibleParents, Monitor mnt, GAParameters settings)
Definition: EAUtils.java:645
static Candidate buildCandidateByFragmentingMolecule(IAtomContainer mol, Monitor mnt, GAParameters settings, int index)
Generates a candidate by fragmenting a molecule and generating the graph that reconnects all fragment...
Definition: EAUtils.java:943
static void createFolderForGeneration(int genId, GAParameters settings)
Creates a folder meant to hold all the data generated during a generation.
Definition: EAUtils.java:148
static void outputPopulationDetails(Population population, String filename, GAParameters settings, boolean printpathNames)
Write out summary for the current GA population.
Definition: EAUtils.java:1324
static String getPathNameToGenerationFolder(int genID, GAParameters settings)
Definition: EAUtils.java:1568
static double getPopulationSD(Population molPopulation)
Check if fitness values have significant standard deviation.
Definition: EAUtils.java:2114
static Candidate buildCandidateFromScratch(Monitor mnt, GAParameters settings)
Definition: EAUtils.java:842
static String getPathNameToGenerationDetailsFile(int genID, GAParameters settings)
Definition: EAUtils.java:1584
static Population importInitialPopulation(SizeControlledSet uniqueIDsSet, GAParameters settings)
Reads unique identifiers and initial population file according to the GAParameters.
Definition: EAUtils.java:162
DENOPTIM's evolutionary algorithm.
List< Candidate > makeOffspringA(List< Candidate > eligibleParents, Population population, Monitor mnt)
Generates one offspring according to the method where crossover and mutation are decoupled,...
EvolutionaryAlgorithm(GAParameters settings, ExternalCmdsListener cmdListener)
void cleanupAsync()
Removes all tasks whether they are completed or not.
final ExternalCmdsListener cmdListener
Service watching for external commands.
boolean stopped
Flag signaling this EA was stopped.
int processInitialPopCandidate(Candidate candidate, Population population, Monitor mnt, List< Task > batchOfSyncParallelTasks, int attemptsToFillBatch, boolean replaceWorstPopMember, boolean candidatesOverflow)
List< String > candidatesToAdd
List of IDs of candidates to be evaluated upon request from the user.
boolean evolvePopulation(Population population, int genId)
Generates a given number of new candidate items and adds them to the current population.
void cleanupCompleted()
Removes only tasks that are marked as completed.
void addCandidates(Set< String > pathNames)
Adds candidate IDs to the list of "to-be-included" candidates.
boolean isAsync
Flag determining the use of asynchronous parallelization scheme.
List< FitnessTask > submitted
Temporary storage of fitness evaluation tasks just submitted to asynchronous Parallelization scheme.
TasksBatchManager tbm
Task manager for tasks to be executed as batches.
void submitSyncParallelBatch(List< Task > batchOfSyncParallelTasks)
ThreadPoolExecutor tpe
Execution service used in asynchronous parallelization scheme.
Set< String > candidatesToRemove
List of IDs of candidates to be removed from the population.
SizeControlledSet scs
Storage of unique identifiers encountered by this instance.
Throwable ex
Issue emerging from a thread submitted by asynchronous parallelization scheme.
GAParameters settings
Parameters controlling the execution of this evolutionary algorithm.
void removeCandidates(Set< String > candID)
Adds candidate IDs to the list of "to-be-removed" candidates.
void initializePopulation(Population population)
Fills up the population with candidates build from scratch.
List< Candidate > makeOffspringB(List< Candidate > eligibleParents, Population population, Monitor mnt)
Generates one offspring according to the method where crossover and mutation are coupled,...
Map< FitnessTask, Future< Object > > futures
Temporary storage of future results produced by fitness evaluation tasks submitted to asynchronous pa...
Logger logger
Program-specific logger.
Service that watches the interface folder (i.e., see GAParameters#interfaceDir) for instructions comi...
void setReferenceToRunningEAlgorithm(EvolutionaryAlgorithm ea)
Task that calls the fitness provider for an offspring that can become a member of the current populat...
A collection of candidates.
Definition: Population.java:48
void trim(int populationSize)
Removes all the elements exceeding the given size.
A candidate is the combination of a denoptim graph with molecular representation and may include also...
Definition: Candidate.java:40
void setGeneration(int genId)
Definition: Candidate.java:565
void setLocalMsg(String msg)
Definition: DGraph.java:279
An iterator that take IAtomContainers from a file, possibly using an available iterating reader,...
A collection of counters user to count actions taken by the evolutionary algorithm.
Definition: Monitor.java:37
void increase(CounterID cid)
Definition: Monitor.java:149
void printHeader(String pathName)
Definition: Monitor.java:177
boolean containsParameters(ParametersType type)
RunTimeParameters getParameters(ParametersType type)
Logger getLogger()
Get the name of the program specific logger.
Randomizer getRandomizer()
Returns the current program-specific randomizer.
Parameters for genetic algorithm.
boolean dumpMonitor
Flag controlling if we dump monitored data or not.
int maxUIDMemory
Maximum number of unique identifiers kept in memory.
boolean parentsSurvive
Flag defining if population members can survive multiple generations (when this variable is true) or ...
String uidMemoryOnDisk
Text file used to store unique identifiers beyond the limits of the memory (see GAParameters#maxUIDMe...
boolean coupleMutationAndCrossover
Flag defining if we want mutation to occur on offspring that result from crossover (i....
Parameters controlling execution of the fragmenter.
void setWorkingIn3D(boolean workingIn3D)
Sets boolean variable workingIn3D.
Task that assesses the fitness of a given graph.
Class that manages the submission of a batch of tasks.
List< Candidate > executeTasks(List< Task > syncronisedTasks, int numOfProcessors)
Execute the list of tasks.
Class meant to collect unique strings without leading to memory overflow.
synchronized boolean addNewUniqueEntry(String entry)
Checks if the given entry is already container in the set of known entries and, if not,...
A chosen method for generation of new Candidates.
Definition: EAUtils.java:133
Identifier of a counter.
Definition: CounterID.java:29
FRG_PARAMS
Parameters controlling the fragmenter.
FIT_PARAMS
Parameters pertaining the calculation of fitness (i.e., the fitness provider).