Commit fcc1cb0f authored by Christian Reuschling's avatar Christian Reuschling
Browse files

added candidate vector metadata functionality | new data container specifications with Lombok

parent f60a56f9
......@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.dfki.sds</groupId>
<artifactId>genIe</artifactId>
<version>1.0-SNAPSHOT</version>
<version>1.0</version>
<packaging>jar</packaging>
<name>genIe</name>
<url>http://leechcrawler.github.com/leech/</url>
......@@ -65,7 +65,7 @@
<dependency>
<groupId>de.dfki.sds</groupId>
<artifactId>inquisitor</artifactId>
<version>23_1-SNAPSHOT</version>
<version>23_2-SNAPSHOT</version>
</dependency>
<dependency>
......
......@@ -2,13 +2,70 @@ package de.dfki.sds.genie;
import javax.print.*;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.JobSheets;
import javax.print.attribute.standard.MediaSizeName;
import java.io.IOException;
import java.io.OutputStream;
public class FeldWaldWiese
{
public static void main(String[] args)
{
DocFlavor[] docFlavorsAccepted =
{DocFlavor.INPUT_STREAM.JPEG, DocFlavor.INPUT_STREAM.JPEG, DocFlavor.INPUT_STREAM.PNG, DocFlavor.INPUT_STREAM.GIF, DocFlavor.INPUT_STREAM.TEXT_PLAIN_HOST,
DocFlavor.INPUT_STREAM.TEXT_HTML_HOST, DocFlavor.INPUT_STREAM.TEXT_HTML_HOST, DocFlavor.INPUT_STREAM.POSTSCRIPT,//7
DocFlavor.INPUT_STREAM.PDF};
int iFlavour = 7;
StreamPrintServiceFactory[] prservFactories =
StreamPrintServiceFactory.lookupStreamPrintServiceFactories(null, null);
if (null == prservFactories || 0 >= prservFactories.length)
{
System.err.println("sErrNoPrintService");
System.exit(2);
}
DocFlavor flavor = docFlavorsAccepted[iFlavour];
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(MediaSizeName.ISO_A4);
}
StreamPrintService streamPrintService = prservFactories[0].getPrintService(new OutputStream()
{
@Override
public void write(int b) throws IOException
{
}
});
JobSheets jobSheets = (JobSheets) streamPrintService.getDefaultAttributeValue(JobSheets.class);
System.out.println(jobSheets);
PrintService[] pservices = PrintServiceLookup.lookupPrintServices(flavor, aset);
if (pservices.length > 0)
{
PrintService service = pservices[0];
DocPrintJob pj = service.createPrintJob();
boolean mNoJobSheet = false;
JobSheets js = (JobSheets) (service.getDefaultAttributeValue(JobSheets.class));
if (js != null && js.equals(JobSheets.NONE))
{
mNoJobSheet = true;
}
System.out.println(mNoJobSheet);
}
}
}
package de.dfki.sds.genie;
import de.dfki.sds.genie.genetic.CandidateVectorWithMetadata;
import java.util.List;
public interface FitnessCalculator
{
/**
* Calculates a score out of a given parameter combination. In the case you want to have the vector-index-according parameter names, have a look into the candidate object.
* It is ok to change the candidates' metadata inside the given Object. This metadata will be given to all offsprings of this vector.
*
* @param candidate The candidate solution to calculate fitness for. In the case you want to have the vector-index-according parameter names, look into the candidate object
* @param population The entire population. This will include the specified candidate. This is provided for fitness evaluators that evaluate individuals in the
* context of the population that they are part of (e.g. a program that evolves game-playing strategies may wish to play each strategy against each of the
* others). This parameter can be ignored by simple fitness evaluators. When iterating over the population, a simple reference equality check (==) can be
* used to identify which member of the population is the specified candidate.
*
* @return The fitness score for the specified candidate. Must always be a non-negative value regardless of natural or non-natural evaluation is being used.
*/
abstract double calculateFitness(CandidateVectorWithMetadata candidate, List<? extends CandidateVectorWithMetadata> population) throws Exception;
}
......@@ -5,24 +5,21 @@ package de.dfki.sds.genie;
import com.cedarsoftware.util.io.JsonObject;
import com.cedarsoftware.util.io.JsonReader;
import com.cedarsoftware.util.io.JsonWriter;
import de.dfki.inquisitor.cache.LRUCache;
import de.dfki.inquisitor.collections.CollectionUtilz;
import de.dfki.inquisitor.collections.MultiValueConfiguration;
import de.dfki.inquisitor.text.StringUtils;
import de.dfki.inquisitor.streams.StreamUtilz;
import de.dfki.sds.genie.genetic.CandidateVectorWithMetadata;
import de.dfki.sds.genie.genetic.GeneticParamOptimizer;
import lombok.Data;
import de.dfki.sds.genie.genetic.GeneticRunConfig;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
......@@ -30,26 +27,23 @@ import java.util.regex.Pattern;
@Accessors(chain = true, prefix = {"m_d", "m_f", "m_str", "m_l", "m_hs", "m_s", "m_", "d", "f", "str", "l", "hs", "s", ""})
public class GenIe extends GeneticParamOptimizer
{
@Accessors(chain = true, prefix = {"m_d", "m_f", "m_str", "m_l", "m_hs", "m_s", "m_", "d", "f", "str", "l", "hs", "s", ""})
@Data
public static class ByteArrayContainer
{
byte[] m_byteArray;
}
public static void main(String[] args)
{
// TODO wir würden gerne auch eine programatische Schnittstelle mit einem fittnesscalculator bieten. in der Main wird dann ein execFitnessCalculator gesetzt, der die
// jetzige Methodenimplementierung enthält...und in die Doku noch die Möglichkeit Gods zu setzen, damit man eingreifen kann
// TODO Joachim Projekt
// TODO Andreas fragen wg openSource, vorstellen in der Gruppe
// TODO dann kann ich mir die Implementierung im inquisitor auch schenken - bevor ich das aber wegschmeisse ändern wir die Inquisitor-Versionsnummer, das ist dann nicht
// mehr abwärtskompatibel
// TODO Christoph zeigen, weitere Schritte
// TODO In meiner neuen HomePage referenzieren
GenIe geneticOptimizer = new GenIe();
......@@ -71,39 +65,20 @@ public class GenIe extends GeneticParamOptimizer
static public String getStreamTail(InputStream inputStream, int iLastCharCount) throws IOException
{
// TODO in den Inquisitor?
LRUCache<ByteArrayContainer, Integer> lQueue = new LRUCache<>(2);
ByteArrayOutputStream resultStream = new ByteArrayOutputStream();
int iByteReadCount = 0;
while (iByteReadCount != -1)
{
ByteArrayContainer container = new ByteArrayContainer().setByteArray(new byte[iLastCharCount * 4]);
iByteReadCount = inputStream.read(container.m_byteArray);
if (iByteReadCount != -1)
lQueue.put(container, iByteReadCount);
}
lQueue.forEach((container, byteReadCount) -> resultStream.write(container.getByteArray(), 0, byteReadCount));
String strTail = resultStream.toString(StandardCharsets.UTF_8);
if (strTail.length() > iLastCharCount)
return StringUtils.lastChars(strTail, iLastCharCount).toString();
return strTail;
}
@CommandLine.Option(names = {"-c", "--configFile"}, description = "The file path to the genIe configuration that should be used")
protected String m_strConfigPath = "geneticOptimization.conf";
@Setter
protected List<String> m_lIndependentParamNames;
@Setter
protected FitnessCalculator m_fitnessCalculator;
@CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "display this help message")
boolean usageHelpRequested;
@Setter
LinkedHashMap<String, List<String>> m_hsParamNames2DiscreteValSpaces;
......@@ -119,6 +94,14 @@ public class GenIe extends GeneticParamOptimizer
try
{
// wenn wir programatisch einen gesetzt haben, nehmen wir den. Ansonsten triggern wir den konfigurierten exec call
if (m_fitnessCalculator != null)
return m_fitnessCalculator.calculateFitness(candidate, population);
// we invoke the configred exec call as default
LinkedList<String> lCommand = new LinkedList<>();
String strCommandPath = m_geneticRunConfig.m_geneticConfig.getUniqueAsString("fitnessFunctionExecPath");
......@@ -135,7 +118,7 @@ public class GenIe extends GeneticParamOptimizer
ProcessBuilder builder = new ProcessBuilder(lCommand);
Process process = builder.start();
String strOutputTail = getStreamTail(process.getInputStream(), 10000);
String strOutputTail = StreamUtilz.getStreamTail(process.getInputStream(), 10000);
int returnCode = process.waitFor();
if (returnCode != 0)
......@@ -168,4 +151,59 @@ public class GenIe extends GeneticParamOptimizer
throw new RuntimeException(e);
}
}
/**
* Offers the parameters that should be optimized. Each parameter has a position (the order of the LinkedHashMap is the vector order), a name (the keys) and a list of
* possible values. These values are specified as discrete strings, and are picked from the genetic algorithm as candidates. The values can be arbitrary, and are just
* offered in the candidate vector to the fitness function {@link #calculateFitness(CandidateVectorWithMetadata, List)} you also have to implement.<br>
* <li><b>CAUTION</b>: the <b>FIRST</b> value of each value space list will be used as the constant value for this parameter during the independent parameter check.
* Make sure that this is a sensefull, valid one as possible.
* <li>In the case a value space consists only out of numbers, the class will recognize this. This makes no difference regarding the genetic algorithm - the String
* values will be simply picked as specified - but in the impact calculation of this attribute.
*
* @return the parameter names together with their possible value candidates, with the <b>FIRST</b> value picked for independent parameter value check
*/
@Override
protected LinkedHashMap<String, List<String>> createParamNames2DiscreteValSpaces()
{
if (m_hsParamNames2DiscreteValSpaces != null)
return m_hsParamNames2DiscreteValSpaces;
// die Oberklasse holt es aus der config
return super.createParamNames2DiscreteValSpaces();
}
/**
* Offers the independent parameter names that should be optimized, that are potentially not interfer with other parameters. The benefit is, that you can check these
* parameters easily by just making the loop over their values and get the best one for each, holding all other parameter values constant/fixed. The complexity is
* then paramValCount+paramValCount+... instead of paramValCount*paramValCount*... for getting all combinations.<br>
* <li>To check an independent parameter value, the class makes a simple loop over the parameters values. The other parameters are set to the <b>FIRST</b> value of
* their value space list, as given with {@link #createParamNames2DiscreteValSpaces()}
* <li>In the case a value space consists only out of numbers, the class will recognize this. This makes no difference regarding the genetic algorithm - the String
* values will be simply picked as specified - but in the impact calculation of this attribute.
* <li>note if 'useOptimizedParamsDuringIndependentParamsCheck is set to true, the order of the parameters might be relevant
* <li>You can specify parameter names double - in this case the loop rechecks this parameter after the succeeding parameters
*
* @return the independent parameter names
*/
@Override
protected List<String> getIndependentParamNames()
{
if (m_lIndependentParamNames != null)
return m_lIndependentParamNames;
// die Oberklasse holt es aus der config
return super.getIndependentParamNames();
}
public CandidateVectorWithMetadata optimizeParams(String path2configFile)
{
return optimizeParams(GeneticRunConfig.createFromFile(path2configFile));
}
}
......@@ -17,11 +17,21 @@ import java.util.List;
@Data
public class CandidateVectorWithMetadata
{
public CandidateVectorWithMetadata(List<String> paramNames)
{
}
/**
* The vector that will be optimized
*/
List<String> m_lCandidateVector;
/**
* The names of the vector parameters, in the same order as the values inside the candidate
*/
List<String> m_lCandidateVectorParamNames;
/**
* Optional. Some arbitrary metadata given from the cost function (or maybe initially from the config for the first generation)
*/
......@@ -44,12 +54,14 @@ public class CandidateVectorWithMetadata
public CandidateVectorWithMetadata copyDeep2clone()
public CandidateVectorWithMetadata cloneDeep()
{
CandidateVectorWithMetadata clone = new CandidateVectorWithMetadata();
// wie don't copy the param names - this would be really unnecessary waste
CandidateVectorWithMetadata clone = new CandidateVectorWithMetadata(this.m_lCandidateVectorParamNames);
if (this.m_lCandidateVector != null)
clone.setCandidateVector(new ArrayList<>(this.m_lCandidateVector));
if (this.getMetadata() != null)
clone.setMetadata(new HashMap<>(this.getMetadata()));
if (this.getParentMetadata() != null)
......
......@@ -87,8 +87,10 @@ public abstract class GeneticParamOptimizer
// CandidateVectorWithMetadata
List<List<String>> lVectors = m_listCrossover.publicMate(parent1.getCandidateVector(), parent2.getCandidateVector(), numberOfCrossoverPoints, rng);
CandidateVectorWithMetadata offspring1 = new CandidateVectorWithMetadata().setCandidateVector(lVectors.get(0));
CandidateVectorWithMetadata offspring2 = new CandidateVectorWithMetadata().setCandidateVector(lVectors.get(1));
CandidateVectorWithMetadata offspring1 =
new CandidateVectorWithMetadata(parent1.m_lCandidateVectorParamNames).setCandidateVector(lVectors.get(0));
CandidateVectorWithMetadata offspring2 =
new CandidateVectorWithMetadata(parent1.m_lCandidateVectorParamNames).setCandidateVector(lVectors.get(1));
// Die Nachkommen kriegen die Metadaten und die scores ihrer Eltern mit
......@@ -124,7 +126,7 @@ public abstract class GeneticParamOptimizer
// wir ersetzen noch die Werte der independent parameter auf die ermittelt besten
replaceIndependentParamValsWithBestOnes(lCandidate);
CandidateVectorWithMetadata candidate = new CandidateVectorWithMetadata().setCandidateVector(lCandidate);
CandidateVectorWithMetadata candidate = new CandidateVectorWithMetadata(m_alParamNames).setCandidateVector(lCandidate);
// initiales Metadatenset
candidate.setParentMetadata(List.of(m_geneticRunConfig.m_firstGenerationParentMetadata));
......@@ -252,6 +254,7 @@ public abstract class GeneticParamOptimizer
static protected Logger log = LoggerFactory.getLogger(GeneticParamOptimizer.class);
protected ArrayList<TwoValuesBox<String, List<String>>> m_alParamNames2DiscreteValSpace;
protected List<String> m_alParamNames;
protected boolean m_bInitialized = false;
protected FitnessEvaluator<CandidateVectorWithMetadata> m_cachedFitnessEvaluator;
protected HallOfFameEvolutionObserver m_hallOfFameObserver;
......@@ -536,7 +539,7 @@ public abstract class GeneticParamOptimizer
{
lCandidate4Param.set(getVectorIndex4Param(strParamName), strParamValue);
CandidateVectorWithMetadata candidate = new CandidateVectorWithMetadata().setCandidateVector(lCandidate4Param);
CandidateVectorWithMetadata candidate = new CandidateVectorWithMetadata(m_alParamNames).setCandidateVector(lCandidate4Param);
candidate.setParentMetadata(List.of(m_geneticRunConfig.m_firstGenerationParentMetadata));
// die Götter haben das letzte Wort, um zB einen validen Vektor zu erzeugen
......@@ -544,7 +547,7 @@ public abstract class GeneticParamOptimizer
candidate = god.proofInitialCandidate(candidate);
// wir erzeugen ein neues Objekt - das verwendete sollte immutable sein, und so stellen wir wenigstens sicher daß wir hier nicht was verändern
CandidateVectorWithMetadata clone = candidate.copyDeep2clone();
CandidateVectorWithMetadata clone = candidate.cloneDeep();
double dFitness = m_cachedFitnessEvaluator.getFitness(clone, null);
......@@ -601,8 +604,7 @@ public abstract class GeneticParamOptimizer
lStats4VectorIndicesSorted = lStats.stream().sorted(Comparator.comparing(stats4Value -> stats4Value.bestFitness)).collect(Collectors.toList());
else
lStats4VectorIndicesSorted =
lStats.stream().sorted(Comparator.comparing(stats4Value -> ((ParamValuesFitnessStats) stats4Value).bestFitness).reversed())
.collect(Collectors.toList());
lStats.stream().sorted(Comparator.comparing(stats4Value -> ((ParamValuesFitnessStats) stats4Value).bestFitness).reversed()).collect(Collectors.toList());
StringBuilder strbReport =
......@@ -691,12 +693,14 @@ public abstract class GeneticParamOptimizer
m_lhsParamNames2DiscreteValSpace = createParamNames2DiscreteValSpaces();
m_alParamNames2DiscreteValSpace = new ArrayList<>(m_lhsParamNames2DiscreteValSpace.size());
m_alParamNames = new ArrayList<>(m_lhsParamNames2DiscreteValSpace.size());
int i = 0;
for (Entry<String, List<String>> paramName2ValSpace : m_lhsParamNames2DiscreteValSpace.entrySet())
{
m_alParamNames2DiscreteValSpace.add(new TwoValuesBox<>(paramName2ValSpace.getKey(), paramName2ValSpace.getValue()));
m_hsParamName2VectorPosition.put(paramName2ValSpace.getKey(), i++);
m_alParamNames.add(paramName2ValSpace.getKey());
}
......@@ -791,7 +795,7 @@ public abstract class GeneticParamOptimizer
// als Erstes machen wir zum Checken die loop, vielleicht erlangen wir dadurch ja schon weitere Erkenntnisse
TwoValuesBox<List<String>, String> independenceCheckResult = independenceCheck();
List<String> lBestCandidate4Check = independenceCheckResult.getFirst();
CandidateVectorWithMetadata bestCandidate4Check = new CandidateVectorWithMetadata().setCandidateVector(lBestCandidate4Check);
CandidateVectorWithMetadata bestCandidate4Check = new CandidateVectorWithMetadata(m_alParamNames).setCandidateVector(lBestCandidate4Check);
bestCandidate4Check.setParentMetadata(List.of(m_geneticRunConfig.m_firstGenerationParentMetadata));
......@@ -832,11 +836,11 @@ public abstract class GeneticParamOptimizer
SelectionStrategy selectionStrategy;
if (m_geneticRunConfig.m_geneticConfig.getUniqueAsString("selectionStrategy").equals("RouletteWheelSelection"))
if ("RouletteWheelSelection".equals(m_geneticRunConfig.m_selectionStrategy))
selectionStrategy = new RouletteWheelSelection();
else if (m_geneticRunConfig.m_geneticConfig.getUniqueAsString("selectionStrategy").equals("StochasticUniversalSampling"))
else if ("StochasticUniversalSampling".equals(m_geneticRunConfig.m_selectionStrategy))
selectionStrategy = new StochasticUniversalSampling();
else if (m_geneticRunConfig.m_geneticConfig.getUniqueAsString("selectionStrategy").equals("SigmaScaling"))
else if ("SigmaScaling".equals(m_geneticRunConfig.m_selectionStrategy))
selectionStrategy = new SigmaScaling();
else
selectionStrategy = new SigmaScaling();
......
......@@ -4,6 +4,8 @@ package de.dfki.sds.genie.genetic;
import de.dfki.inquisitor.collections.CollectionUtilz;
import de.dfki.inquisitor.collections.MultiValueConfiguration;
import lombok.Data;
import lombok.experimental.Accessors;
import org.slf4j.LoggerFactory;
import org.uncommons.watchmaker.framework.TerminationCondition;
import org.uncommons.watchmaker.framework.termination.ElapsedTime;
......@@ -16,7 +18,8 @@ import java.util.LinkedList;
import java.util.List;
@Accessors(chain = true, prefix = {"m_d", "m_f", "m_b", "m_str", "m_l", "m_hs", "m_s", "m_", "d", "f", "b", "str", "l", "hs", "s", ""})
@Data
public class GeneticRunConfig
{
......@@ -25,6 +28,9 @@ public class GeneticRunConfig
{
return new GeneticRunConfig().load(new MultiValueConfiguration(new File(path2config)));
}
public boolean m_bConstantRandomSeed = true;
public boolean m_bLowerScoreIsBetter = false;
public boolean m_bRuntimeFitness = false;
......@@ -35,6 +41,7 @@ public class GeneticRunConfig
public int m_eliteCount;
public int m_epochLength;
public int m_firstPopulationSize;
public String m_selectionStrategy;
public MultiValueConfiguration m_geneticConfig;
public int m_iEvaluateLastWinnersCount;
public int m_islandCount;
......@@ -49,6 +56,8 @@ public class GeneticRunConfig
public GeneticRunConfig load(MultiValueConfiguration geneticConfig)
{
......@@ -82,6 +91,7 @@ public class GeneticRunConfig
m_bLowerScoreIsBetter = true;
}
m_selectionStrategy = m_geneticConfig.getUniqueAsString("selectionStrategy");
m_firstPopulationSize = geneticConfig.getUniqueAsInteger("firstPopulationSize");
m_populationSize = geneticConfig.getUniqueAsInteger("populationSize");
......
......@@ -3,58 +3,31 @@ package de.dfki.sds.genie;
import de.dfki.sds.genie.genetic.CandidateVectorWithMetadata;
import de.dfki.sds.genie.genetic.GeneticParamOptimizer;
import de.dfki.sds.genie.genetic.GeneticRunConfig;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.HashMap;
import java.util.List;
public class Sum23Test extends GeneticParamOptimizer
public class Sum23Test
{
@Accessors(chain = true, prefix = {"m_d", "m_f", "m_str", "m_l", "m_hs", "m_s", "m_", "d", "f", "str", "l", "hs", "s", ""})
@Data
public static class ScoreWithMetadata
{
double m_dScore = 0;
HashMap<String, String> m_hsMetadata = new HashMap<>();
}
public static void main(String[] args)
{
// TODO hier nehmen wir den Vektor mit parentmetadaten und parentscores an, berechnen die Fitness, generieren neue Metadaten und geben beides in stdOut als Json aus
CandidateVectorWithMetadata bestVectorWithMetadata =
new Sum23Test().optimizeParams(GeneticRunConfig.createFromFile("src/test/java/de/dfki/sds/genie/geneticOptimization.conf"));
}
@Override
protected double calculateFitness(CandidateVectorWithMetadata candidate, List<? extends CandidateVectorWithMetadata> population) throws Exception
{
// hier können wir die Metadaten im candidate verändern - Nachkommen kriegen immer einen Klon
int iSum = candidate.getCandidateVector().stream().mapToInt(Integer::valueOf).sum();
CandidateVectorWithMetadata bestVector = new GenIe().setFitnessCalculator((candidate, population) -> {
int iSum = candidate.getCandidateVector().stream().mapToInt(Integer::valueOf).sum();
ScoreWithMetadata scoreWithMetadata = new ScoreWithMetadata().setScore(0d);
if (iSum == 23)
return 0.9d;
if (iSum == 23)
scoreWithMetadata.setScore(0.9d);
return 0d;
}).optimizeParams("src/test/java/de/dfki/sds/genie/geneticOptimization.conf");
// CandidateVectorWithMetadata bestVector = new GenIe().optimizeParams("src/test/java/de/dfki/sds/genie/geneticOptimization.conf");
return scoreWithMetadata.getScore();
}
}
......@@ -2,83 +2,107 @@
### Genetic config
# Calculates the fitness as specified by the implementing class, but uses as final fitness the runtime needed to calculate the fitness. Lower score is better in this
# case (lower runtime), cache is disabled. This can be used for searching time-consuming parameters
# Calculates the fitness as specified by the fitness function, but uses as final fitness the runtime needed to calculate the fitness. Lower score is
# better in this case (lower runtime), caches are disabled. This can be used for searching time-consuming parameters
runtimePerformanceCheck=false
# Show more log messages
verbose=true
# If false, if an exception was thrown during fitness calculation, the optimization process won't be interrupted, just a log message will be shown
# If an exception was thrown during fitness calculation, the optimization process won't be interrupted, just a log message will be shown
interruptIfException=true
# After genetic optimization an entropy analysis of the last N generation winners will be shown
# After genetic optimization, an entropy analysis of the last N generation winners will be shown. Here you can specify the number of winners
evaluateLastWinnersCount=42
# Shows a small window with information to the optimization process, e.g. the current generation fitness values
showMonitorGui=true
# Whether to use an in-memory or a persistent cache. In the case of runtimePerformanceCheck=true, the caches are disabled
# Weak references for an in-memory cache. Can help with exploding memory consumption
weakRefCache=false
# if set, a persistent cache is used
# If set, a persistent cache is used. If the value is empty, GenIe uses an in-memory cache
persistentCacheDir=
# if multithreaded, the system uses as many threads as cpu cores
# Parallelize the vector fitness calculations. If multithreaded, the system uses as many threads as cpu cores
singleThreaded=true
## The optimizer first performs a loop over all given values of this parameter, whereby the default(first given) value of the other parameters stay fixed. if true, the
# succeeding genetic run will be skipped