$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.bcel.generic.RETURN;
39import org.apache.commons.lang3.time.StopWatch;
40import org.openscience.cdk.io.iterator.IteratingSMILESReader;
41
42import denoptim.exception.DENOPTIMException;
43import denoptim.exception.ExceptionUtils;
44import denoptim.fitness.FitnessParameters;
45import denoptim.ga.EAUtils.CandidateSource;
46import denoptim.graph.Candidate;
47import denoptim.io.IteratingAtomContainerReader;
48import denoptim.logging.CounterID;
49import denoptim.logging.Monitor;
50import denoptim.programs.RunTimeParameters.ParametersType;
51import denoptim.programs.denovo.GAParameters;
52import denoptim.programs.fragmenter.FragmenterParameters;
53import denoptim.task.FitnessTask;
54import denoptim.task.Task;
55import denoptim.task.TasksBatchManager;
56import denoptim.utils.SizeControlledSet;
57
94{
99
104
108 private boolean stopped = false;
109
114 private Set<String> candidatesToRemove = new HashSet<String>();
115
121 private List<String> candidatesToAdd = new ArrayList<String>();
122
126 private boolean isAsync = true;
127
132 private Map<FitnessTask,Future<Object>> futures;
133
138 private List<FitnessTask> submitted;
139
143 private ThreadPoolExecutor tpe;
144
149
154 private Throwable ex;
155
160
164 private Logger logger = null;
165
166 private final String NL = System.getProperty("line.separator");
167
168//------------------------------------------------------------------------------
169
172 {
173 this.settings = settings;
174 this.logger = settings.getLogger();
175 this.cmdListener = cmdListener;
176
177 // There is currently nothing to initialize for the synchronous scheme
179 {
180 isAsync = false;
181 tbm = new TasksBatchManager();
182
183 } else {
184 isAsync = true;
185 futures = new HashMap<FitnessTask,Future<Object>>();
186 submitted = new ArrayList<>();
187
188 tpe = new ThreadPoolExecutor(settings.getNumberOfCPU(),
190 TimeUnit.MILLISECONDS,
191 new ArrayBlockingQueue<Runnable>(1));
192
193 Runtime.getRuntime().addShutdownHook(new Thread()
194 {
195 @Override
196 public void run()
197 {
198 tpe.shutdown(); // Disable new tasks from being submitted
199 try
200 {
201 // Wait a while for existing tasks to terminate
202 if (!tpe.awaitTermination(30, TimeUnit.SECONDS))
203 {
204 tpe.shutdownNow(); //Cancel running tasks
205 }
206 if (!tpe.awaitTermination(60, TimeUnit.SECONDS))
207 {
208 // pool didn't terminate after the second try
209 }
210 }
211 catch (InterruptedException ie)
212 {
213 cleanupAsync();
214 // (Re-)Cancel if current thread also interrupted
215 tpe.shutdownNow();
216 // Preserve interrupt status
217 Thread.currentThread().interrupt();
218 }
219 }
220 });
221
222 // by default the ThreadPoolExecutor will throw an exception
223 tpe.setRejectedExecutionHandler(new RejectedExecutionHandler()
224 {
225 @Override
226 public void rejectedExecution(Runnable r,
227 ThreadPoolExecutor executor)
228 {
229 try
230 {
231 // this will block if the queue is full
232 executor.getQueue().put(r);
233 }
234 catch (InterruptedException ex)
235 {
236 //nothing, really
237 }
238 }
239 });
240 }
241
245 }
246
247//------------------------------------------------------------------------------
248
249 public void run() throws DENOPTIMException
250 {
252
253 StopWatch watch = new StopWatch();
254 watch.start();
255 if (isAsync)
256 {
257 tpe.prestartAllCoreThreads();
258 }
259 Monitor mnt = new Monitor();
261
262 // Create initial population of candidates
264 Population population;
265 try
266 {
268 } catch (Exception e)
269 {
270 throw new DENOPTIMException("Unable to import initial population.",
271 e);
272 }
273 initializePopulation(population);
274
275 boolean writeCandsOnDisk = ((FitnessParameters) settings.getParameters(
276 ParametersType.FIT_PARAMS)).writeCandidatesOnDisk();
279 settings, writeCandsOnDisk);
280
281 // Ensure that there is some variability in fitness values
282 double sdev = EAUtils.getPopulationSD(population);
283 if (sdev < settings.getMinFitnessSD())
284 {
285 String msg = "Fitness values have negligible standard deviation "
286 + "(STDDEV=" + String.format("%.6f", sdev) + "). "
287 + "Abbandoning evolutionary algorithm.";
288 logger.log(Level.SEVERE, msg);
289 population.trim(0);
290 return;
291 }
292
293 // Start evolution cycles, i.e., generations
294 int numStag = 0, genId = 1;
295 while (genId <= settings.getNumberOfGenerations())
296 {
297 logger.log(Level.INFO,"Starting Generation {0}"
298 + NL, genId);
299
300 String txt = "No change";
301 try
302 {
303 if (!evolvePopulation(population, genId))
304 {
305 numStag++;
306 }
307 else
308 {
309 numStag = 0;
310 txt = "New members introduced";
311 }
312 } catch (DENOPTIMException e)
313 {
314 logger.log(Level.SEVERE, "Exception while running evolutionary"
315 + "algorithm. Details: " + NL
317 throw e;
318 }
319
320 logger.log(Level.INFO,txt + " in Generation {0}"
321 + NL, genId);
324 settings, writeCandsOnDisk);
325
326 if (stopped)
327 {
328 logger.log(Level.SEVERE,
329 "EA stopped while working on generation {0}. " + NL
330 + "Reporting data for incomplete generation {0}."
331 + NL,genId);
332 break;
333 } else {
334 logger.log(Level.INFO,
335 "Generation {0}" + " completed" + NL
336 + "----------------------------------------"
337 + "----------------------------------------"
338 + NL, genId);
339 }
340
342 {
343 logger.log(Level.WARNING,
344 "No change in population over {0} iterations. "
345 + "Stopping EA." + NL, numStag);
346 break;
347 }
348
349 genId++;
350 }
351
352 if (isAsync)
353 {
354 tpe.shutdown();
355 try
356 {
357 // wait a bit for pending tasks to finish
358 while (!tpe.awaitTermination(5, TimeUnit.SECONDS))
359 {
360 // do nothing
361 }
362 }
363 catch (InterruptedException ex)
364 {
365 //Do nothing
366 }
367 tpe.shutdown();
368 }
369
370 // Sort the population and trim it to desired size
371 Collections.sort(population, Collections.reverseOrder());
373 {
374 population.trim(settings.getPopulationSize());
375 }
376
377 // And write final results
379
380 // Termination
381 population.trim(0);
382 watch.stop();
383 logger.log(Level.INFO, "Overall time: {0}." + NL,
384 watch.toString());
385
386 if (stopped)
387 {
388 logger.info("DENOPTIM EA run stopped." + NL);
389 } else {
390 logger.info("DENOPTIM EA run completed." + NL);
391 }
392 }
393
394//------------------------------------------------------------------------------
395
403 private void initializePopulation(Population population)
404 throws DENOPTIMException
405 {
406 // Deal with existing initial population members
407 synchronized (population)
408 {
409 if (stopped)
410 {
411 return;
412 }
413
414 // Keep only the best candidates if there are too many.
415 Collections.sort(population, Collections.reverseOrder());
416 if (settings.getReplacementStrategy() == 1 &&
417 population.size() > settings.getPopulationSize())
418 {
419 population.trim(settings.getPopulationSize());
420 }
421 }
422 // NB: pop size cannot be > because it has been just trimmed
423 if (population.size() == settings.getPopulationSize())
424 {
425 return;
426 }
427
428 Monitor mnt = new Monitor("MonitorGen",0,settings.getMonitorFile(),
431
432 // Screen molecules (these can be very many!)
434 {
435 IteratingAtomContainerReader iterMolsToFragment = null;
436 try
437 {
438 iterMolsToFragment = new IteratingAtomContainerReader(new File(
440 if (iterMolsToFragment.getIteratorType().equals(
441 IteratingSMILESReader.class))
442 {
445 {
446 frgParams = (FragmenterParameters)
449 }
450 frgParams.setWorkingIn3D(false);
451 }
452 } catch (Exception e1)
453 {
454 throw new DENOPTIMException("Could not set reader on file ''"
456 }
457
458 // This is very similar to the standard population initialization
459 // async loop, but it allows to screen many more candidates because
460 // it keeps only best N, where N is the size of the population.
461 // Yet, there is plenty of repeated code, which is sub-optimal.
462 int i=0;
463 List<Task> batchOfSyncParallelTasks = new ArrayList<>();
464 try
465 {
466 while (iterMolsToFragment.hasNext())
467 {
468 i++;
469
470 if (stopped)
471 {
472 break;
473 }
474
475 if (checkForException())
476 {
477 stopRun();
478 throw new DENOPTIMException("Errors found during sub "
479 + "tasks execution.", ex);
480 }
481
482 Candidate candidate =
484 iterMolsToFragment.next(), mnt, settings, i);
485
486 // NB: here we request to keep only the best candidates
487 // so that the tmp population does not become too large
488 // before being trimmed.
489 i = processInitialPopCandidate(candidate, population, mnt,
490 batchOfSyncParallelTasks, i, true, true);
491 }
492 // We still need to submit the possibly partially-filled last batch
493 if (batchOfSyncParallelTasks.size()>0)
494 submitSyncParallelBatch(batchOfSyncParallelTasks);
495 } catch (DENOPTIMException dex)
496 {
497 if (isAsync)
498 {
499 cleanupAsync();
500 tpe.shutdown();
501 }
502 throw dex;
503 }
504 catch (Exception ex)
505 {
506 if (isAsync)
507 {
508 cleanupAsync();
509 tpe.shutdown();
510 }
511 ex.printStackTrace();
512 throw new DENOPTIMException(ex);
513 }
514 }
515
516 // Loop for creation of candidates until we have created enough new valid
517 // candidates or we have reached the max number of attempts.
518 // WARNING: careful about the duplication of code in this loop and in
519 // the one above (with iterMolsToFragment)
520 int i=0;
521 List<Task> tasks = new ArrayList<>();
522 try
523 {
524 while (i < settings.getPopulationSize() *
526 {
527 i++;
528
529 if (stopped)
530 {
531 break;
532 }
533
534 if (checkForException())
535 {
536 stopRun();
537 throw new DENOPTIMException("Errors found during sub tasks "
538 + "execution.", ex);
539 }
540
541 synchronized (population)
542 {
543 if (population.size() >= settings.getPopulationSize())
544 break;
545 }
546
548 settings);
549
550 i = processInitialPopCandidate(candidate, population, mnt,
551 tasks, i, false, false);
552 }
553 } catch (DENOPTIMException dex)
554 {
555 if (isAsync)
556 {
557 cleanupAsync();
558 tpe.shutdown();
559 }
560 throw dex;
561 }
562 catch (Exception ex)
563 {
564 if (isAsync)
565 {
566 cleanupAsync();
567 tpe.shutdown();
568 }
569 ex.printStackTrace();
570 throw new DENOPTIMException(ex);
571 }
572
573 mnt.printSummary();
574
575 if (i >= (settings.getPopulationSize() *
577 {
578 if (isAsync)
579 {
581 stopRun();
582 }
583 logger.log(Level.SEVERE,
584 "Unable to initialize molecules in {0} attempts."+NL, i);
585
586 throw new DENOPTIMException("Unable to initialize population in "
587 + i + " attempts (Population size: " + population.size()
588 + ", tasks batch size: " + tasks.size() + ").");
589 }
590
591 synchronized (population)
592 {
593 // NB: this does not remove any item from the list
594 population.trimToSize();
595 Collections.sort(population, Collections.reverseOrder());
596 }
597 }
598
599//------------------------------------------------------------------------------
600
617 private int processInitialPopCandidate(Candidate candidate,
618 Population population, Monitor mnt,
619 List<Task> batchOfSyncParallelTasks, int attemptsToFillBatch,
620 boolean replaceWorstPopMember, boolean candidatesOverflow)
621 throws DENOPTIMException
622 {
623 if (candidate == null)
624 return attemptsToFillBatch;
625
626 candidate.setGeneration(0);
627
629 ParametersType.FIT_PARAMS)).checkPreFitnessUID())
630 {
631 try
632 {
633 if (!scs.addNewUniqueEntry(candidate.getUID()))
634 {
635 mnt.increase(CounterID.DUPLICATEPREFITNESS);
636 return attemptsToFillBatch;
637 }
638 } catch (Exception e) {
640 return attemptsToFillBatch;
641 }
642 }
643
645 settings,
646 candidate,
647 null,
649 population, mnt, settings.getUIDFileOut(),
650 replaceWorstPopMember);
651
652 // Submission is dependent on the parallelization scheme
653 if (isAsync)
654 {
655 submitted.add(task);
656 futures.put(task, tpe.submit(task));
657 // We keep some memory but of previous tasks, but must
658 // avoid memory leak due to storage of too many references
659 // to submitted tasks.
660 if (submitted.size() > 2*settings.getNumberOfCPU())
661 {
663 }
664 } else {
665 batchOfSyncParallelTasks.add(task);
666 boolean submitBatch = false;
667 if (!candidatesOverflow)
668 {
669 submitBatch = batchOfSyncParallelTasks.size() >= Math.abs(
670 population.size() - settings.getPopulationSize())
671 ||
672 //This to avoid the fixed batch size to block the
673 //generation of new candidates for too long
674 attemptsToFillBatch >= (0.1 * settings.getPopulationSize() *
676 } else {
677 submitBatch = batchOfSyncParallelTasks.size()
679 }
680 if (submitBatch)
681 {
682 // Now we have as many tasks as are needed to fill up the
683 // population or the batch.
684 // Therefore we can run the execution service.
685 // TasksBatchManager takes the collection of tasks and runs
686 // them in batches of N according to the GA settings.
687 submitSyncParallelBatch(batchOfSyncParallelTasks);
688 } else {
689 attemptsToFillBatch = 0;
690 }
691 }
692 return attemptsToFillBatch;
693 }
694
695//------------------------------------------------------------------------------
696
697 private void submitSyncParallelBatch(List<Task> batchOfSyncParallelTasks)
698 throws DENOPTIMException
699 {
700 tbm.executeTasks(batchOfSyncParallelTasks,
702 batchOfSyncParallelTasks.clear();
703 }
704
705//------------------------------------------------------------------------------
706
715 private boolean evolvePopulation(Population population,
716 int genId) throws DENOPTIMException
717 {
719
720 // Take a snapshot of the initial population members. This to exclude
721 // that offsprings of this generation become parents in this generation.
722 List<Candidate> eligibleParents = new ArrayList<Candidate>();
723 int populationVersion = -1;
724 int newPopSize = -1;
725 synchronized (population)
726 {
727 for (Candidate c : population)
728 {
729 eligibleParents.add(c);
730 }
732 {
733 newPopSize = settings.getNumberOfChildren()
734 + eligibleParents.size();
735 } else {
736 population.clear();
737 newPopSize = settings.getPopulationSize();
738 }
739 populationVersion = population.getVersionID();
740 }
741
742 int i=0;
743 List<Task> syncronisedTasks = new ArrayList<>();
744 Monitor mnt = new Monitor("MonitorGen", genId,
747 try
748 {
749 while (i < settings.getPopulationSize() *
751 {
752 i++;
753
754 if (stopped)
755 {
756 break;
757 }
758
759 if (checkForException())
760 {
761 stopRun();
762 throw new DENOPTIMException("Errors found during sub-tasks "
763 + "execution.", ex);
764 }
765
766 synchronized (population)
767 {
768 synchronized (candidatesToRemove)
769 {
770 if (candidatesToRemove.size()>0)
771 {
772 for (String id : candidatesToRemove)
773 {
774 Candidate c = population.getCandidateNamed(id);
775 if (c != null)
776 {
777 population.remove(c);
778 eligibleParents.remove(c);
779 }
780 }
781 candidatesToRemove.clear();
782 }
783 }
784 }
785
786 synchronized (population)
787 {
788 if (population.size() >= newPopSize)
789 break;
790 }
791
792 File srcOfCandidate = null;
793 List<Candidate> candidatesToEvaluate = new ArrayList<>();
794
795 synchronized (candidatesToAdd)
796 {
797 if (candidatesToAdd.size()>0)
798 {
799 srcOfCandidate = new File(candidatesToAdd.get(0));
800 candidatesToAdd.remove(0);
802 srcOfCandidate, mnt, settings);
803 if (candidate == null)
804 continue;
805 else
806 candidatesToEvaluate.add(candidate);
807 }
808 }
809
810 if (candidatesToEvaluate.size()==0)
811 {
813 {
814 candidatesToEvaluate.addAll(makeOffspringB(
815 eligibleParents, population, mnt));
816 } else {
817 candidatesToEvaluate.addAll(makeOffspringA(
818 eligibleParents, population, mnt));
819 }
820 }
821 if (candidatesToEvaluate.size()==0)
822 continue;
823
824 // NB: for now we assume there can be up to two siblings
825 for (int iSibling=0; iSibling<candidatesToEvaluate.size(); iSibling++)
826 {
827 Candidate candidate = candidatesToEvaluate.get(iSibling);
828 int jSibling = 1;
829 if (iSibling==1)
830 jSibling = 0;
831
832 Candidate sibling = null;
833 if (candidatesToEvaluate.size()>1)
834 sibling = candidatesToEvaluate.get(jSibling);
835
836 candidate.setGeneration(genId);
837
839 ParametersType.FIT_PARAMS)).checkPreFitnessUID())
840 {
841 try
842 {
843 if (!scs.addNewUniqueEntry(candidate.getUID()))
844 {
846 continue;
847 }
848 } catch (Exception e) {
849 mnt.increase(
851 continue;
852 }
853 }
854
856 settings,
857 candidate,
858 sibling,
860 population, mnt, settings.getUIDFileOut(), false);
861
862 if (isAsync)
863 {
864 submitted.add(task);
865 futures.put(task, tpe.submit(task));
866 // We keep some memory of previous tasks, but must
867 // avoid memory leak due to storage of too many references
868 // to submitted tasks.
869 if (submitted.size() > 2*settings.getNumberOfCPU())
870 {
872 }
873 } else {
874 syncronisedTasks.add(task);
875 if (syncronisedTasks.size()
876 >= Math.abs(population.size() - newPopSize)
877 ||
878 //This to avoid the fixed batch size to block the
879 //generation of new candidates for too long
880 i >= (0.1 * settings.getPopulationSize() *
882 {
883 // Now we have as many tasks as are needed to fill up
884 // the population, or we got sick to wait.
885 // TasksBatchManager takes the collection of tasks and
886 // runs them in batches of N, where N is given by the
887 // second argument.
888 submitSyncParallelBatch(syncronisedTasks);
889 }
890 }
891 }
892 }
893 }
894 catch (DENOPTIMException dex)
895 {
896 if (isAsync)
897 {
898 cleanupAsync();
899 tpe.shutdown();
900 }
901 dex.printStackTrace();
902 throw dex;
903 }
904 catch (Exception ex)
905 {
906 if (isAsync)
907 {
908 cleanupAsync();
909 tpe.shutdown();
910 }
911 ex.printStackTrace();
912 throw new DENOPTIMException(ex);
913 }
914
915 mnt.printSummary();
916
917 if (i >= (settings.getPopulationSize() *
919 {
920 if (isAsync)
921 {
923 stopRun();
924 }
925 logger.log(Level.WARNING,
926 "Reached maximum number of attempts (" + i + ") to "
927 + "generate new candidates in generation " + genId + "."
928 + NL);
929 }
930
931 // sort the population and trim it to size
932 synchronized (population)
933 {
934 Collections.sort(population, Collections.reverseOrder());
936 {
937 population.trim(settings.getPopulationSize());
938 }
939 }
940
941 eligibleParents = null;
942 syncronisedTasks.clear();
943
944 // Check if the population has changed
945 int newPopulationVersion = -1;
946 synchronized (population)
947 {
948 newPopulationVersion = population.getVersionID();
949 }
950
951 return populationVersion != newPopulationVersion;
952 }
953
954//------------------------------------------------------------------------------
955
975 @SuppressWarnings("incomplete-switch")
976 private List<Candidate> makeOffspringA(List<Candidate> eligibleParents,
977 Population population, Monitor mnt) throws DENOPTIMException
978 {
980
981 List<Candidate> candidates = new ArrayList<Candidate>();
982 switch (src)
983 {
984 // MANUAL is not a valid choice here
985 case CROSSOVER:
986 {
987 candidates.addAll(EAUtils.buildCandidatesByXOver(
988 eligibleParents, population, mnt, settings));
989 break;
990 }
991
992 case MUTATION:
993 {
995 eligibleParents, mnt, settings);
996 if (candidate!=null)
997 candidates.add(candidate);
998 break;
999 }
1000
1001 case CONSTRUCTION:
1002 {
1004 settings);
1005 if (candidate!=null)
1006 candidates.add(candidate);
1007 break;
1008 }
1009 }
1010 return candidates;
1011 }
1012
1013//------------------------------------------------------------------------------
1014
1036 @SuppressWarnings("incomplete-switch")
1037 private List<Candidate> makeOffspringB(List<Candidate> eligibleParents,
1038 Population population, Monitor mnt) throws DENOPTIMException
1039 {
1045
1046 List<Candidate> candidates = new ArrayList<Candidate>();
1047 switch (src)
1048 {
1049 case CROSSOVER:
1050 {
1051 candidates.addAll(EAUtils.buildCandidatesByXOver(
1052 eligibleParents, population, mnt, settings));
1053 break;
1054 }
1055
1056 case MUTATION:
1057 {
1058 List<Candidate> parents = EAUtils.buildCandidatesByXOver(
1059 eligibleParents, population, mnt, settings);
1060 for (Candidate parent : parents)
1061 {
1062 String provenanceMsg = parent.getGraph().getLocalMsg();
1064 Arrays.asList(parent), mnt, settings);
1065 if (candidate!=null)
1066 {
1067 candidate.getGraph().setLocalMsg("MutationOn" +
1068 provenanceMsg);
1069 candidates.add(candidate);
1070 }
1071 }
1072 break;
1073 }
1074
1075 case CONSTRUCTION:
1076 {
1078 settings);
1079 if (candidate!=null)
1080 candidates.add(candidate);
1081 break;
1082 }
1083 }
1084 return candidates;
1085 }
1086
1087//------------------------------------------------------------------------------
1088
1089 public void stopRun()
1090 {
1091 if (isAsync)
1092 {
1093 cleanupAsync();
1094 tpe.shutdown();
1095 }
1096 stopped = true;
1097 }
1098
1099//------------------------------------------------------------------------------
1100
1104 private void cleanupAsync()
1105 {
1106 for (FitnessTask tsk: submitted)
1107 {
1108 tsk.stopTask();
1109 }
1110 for (FitnessTask tsk : futures.keySet())
1111 {
1112 futures.get(tsk).cancel(true);
1113 }
1114 futures.clear();
1115 submitted.clear();
1116 tpe.getQueue().clear();
1117 }
1118
1119//------------------------------------------------------------------------------
1120
1124 private void cleanupCompleted()
1125 {
1126 List<FitnessTask> completed = new ArrayList<FitnessTask>();
1127
1128 for (FitnessTask t : submitted)
1129 {
1130 if (t.isCompleted())
1131 completed.add(t);
1132 }
1133
1134 for (FitnessTask t : completed)
1135 {
1136 submitted.remove(t);
1137 futures.get(t).cancel(true);
1138 futures.remove(t);
1139 }
1140 }
1141
1142//------------------------------------------------------------------------------
1143
1144 private boolean checkForException()
1145 {
1146 boolean foundExceptions = false;
1147 if (isAsync)
1148 {
1149 for (FitnessTask tsk : submitted)
1150 {
1151 boolean interrupt = false;
1152 synchronized (tsk.lock)
1153 {
1154 if (tsk.foundException())
1155 {
1156 foundExceptions = true;
1157 logger.log(Level.SEVERE, "problems in "
1158 + tsk.toString() + ". ErrorMessage: '"
1159 + tsk.getErrorMessage() + "'. ExceptionInTask: "
1160 + tsk.getException());
1161 ex = tsk.getException().getCause();
1162 interrupt = true;
1163 }
1164 }
1165 if (interrupt)
1166 break;
1167 }
1168 } else {
1169 // We don't really check of exceptions for synchronous scheme
1170 // because the executor service will detect the exception and stop
1171 // the experiment.
1172 }
1173 return foundExceptions;
1174 }
1175
1176//------------------------------------------------------------------------------
1177
1181 public void removeCandidates(Set<String> candID)
1182 {
1183 synchronized (candidatesToRemove)
1184 {
1185 candidatesToRemove.addAll(candID);
1186 }
1187 }
1188
1189//------------------------------------------------------------------------------
1190
1194 public void addCandidates(Set<String> pathNames)
1195 {
1196 synchronized (candidatesToAdd)
1197 {
1198 for (String pathName : pathNames)
1199 {
1200 if (!candidatesToAdd.contains(pathName))
1201 candidatesToAdd.add(pathName);
1202 }
1203 }
1204 }
1205
1206//------------------------------------------------------------------------------
1207
1208}
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:93
static void outputFinalResults(Population popln, GAParameters settings)
Saves the final results to disk.
Definition: EAUtils.java:1515
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:249
static Candidate readCandidateFromFile(File srcFile, Monitor mnt, GAParameters settings)
Definition: EAUtils.java:754
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:279
static CandidateSource chooseGenerationMethod(GAParameters settings)
Choose one of the methods to make new Candidates.
Definition: EAUtils.java:193
static Candidate buildCandidateByMutation(List< Candidate > eligibleParents, Monitor mnt, GAParameters settings)
Definition: EAUtils.java:630
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:928
static void createFolderForGeneration(int genId, GAParameters settings)
Creates a folder meant to hold all the data generated during a generation.
Definition: EAUtils.java:134
static void outputPopulationDetails(Population population, String filename, GAParameters settings, boolean printpathNames)
Write out summary for the current GA population.
Definition: EAUtils.java:1226
static String getPathNameToGenerationFolder(int genID, GAParameters settings)
Definition: EAUtils.java:1449
static double getPopulationSD(Population molPopulation)
Check if fitness values have significant standard deviation.
Definition: EAUtils.java:1989
static Candidate buildCandidateFromScratch(Monitor mnt, GAParameters settings)
Definition: EAUtils.java:827
static String getPathNameToGenerationDetailsFile(int genID, GAParameters settings)
Definition: EAUtils.java:1465
static Population importInitialPopulation(SizeControlledSet uniqueIDsSet, GAParameters settings)
Reads unique identifiers and initial population file according to the GAParameters.
Definition: EAUtils.java:148
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:272
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:119
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).