StandardFile.java
package progen.output.outputers;
import java.util.Map;
import progen.context.ProGenContext;
import progen.kernel.population.Individual;
import progen.output.HistoricalData;
import progen.output.datacollectors.DataCollector;
import progen.output.plugins.Mean;
import progen.output.plugins.Plugin;
/**
* Se genera por la salida estándar una tabla con la información estadística de
* los datos de cada generación.
*
* @author jirsis
* @since 2.0
*
*/
public class StandardFile extends FileOutput {
private static final String FORMAT_3G = "%.3G";
private static final String FORMAT_S_D_N = "%s%d:%n";
private static final String FORMAT_N = "%n";
private static final String FORMAT_S_N_S = "%s%n%s";
private static final String FORMAT_5F = "%.5f";
private static final String FORMAT_3F = "%.3f";
private static final String FORMAT_S = "%s";
private static final String FORMAT_S_S = "%s%s";
private static final String FORMAT_S_N = "%s%n";
private static final String LITERAL_WORST_RUN = "worstRun";
private static final String LITERAL_BEST_RUN = "bestRun";
private static final String LITERAL_GENERATION_MEAN = "generationMean";
private static final String CENTER_SEP = " | ";
private static final String DATACOLLECTOR_POPULATION_TIME_DATA = "PopulationTimeData";
private static final String EXPERIMENT_INDIVIDUAL_DATA = "ExperimentIndividualData";
private static final int EXTRA_PADDING = 3;
private static final String LEFT_SEP = CENTER_SEP.substring(1, 3);
private static final String LITERAL_ADF = "ADF";
private static final String LITERAL_ADJUSTED = "adjusted";
private static final String LITERAL_BREEDING = "breeding";
private static final String LITERAL_DEPTH = "depth";
private static final String LITERAL_EVALUATION = "evaluation";
private static final String LITERAL_FITNESS = "fitness";
private static final String LITERAL_INDIVIDUAL = "individual";
private static final String LITERAL_NODES = "nodes";
private static final String LITERAL_RAW = "raw";
private static final String LITERAL_RBP = "RBP";
private static final String PLUGIN_NAME_BEST = "best";
private static final String PLUGIN_NAME_BREEDING = LITERAL_BREEDING;
private static final String PLUGIN_NAME_EVALUATION = LITERAL_EVALUATION;
private static final String PLUGIN_NAME_MEAN = "mean";
private static final String PLUGIN_NAME_TOTAL = "total";
private static final String RIGHT_SEP = CENTER_SEP.substring(1);
private static final String SINGLE_BLANK_SPACE = " ";
private static final int WIDTH_COLUMN = 10;
/** Datos de un experimento concreto. */
private DataCollector experimentData;
/** Ancho de la primera columna. */
private int firstColumnWidth;
/** Almacén de datos para recuperar. */
private HistoricalData historical;
/** Separador horizontal de filas. */
private String hline;
/** Ancho de la segunda columna. */
private int secondColumnWidth;
private int totalADF;
private int totalRPB;
/**
* Constructor por defecto.
*/
public StandardFile() {
super("standardOutput.txt", true);
historical = HistoricalData.makeInstance();
experimentData = historical.getDataCollectorExperiment(EXPERIMENT_INDIVIDUAL_DATA);
totalRPB = Integer.parseInt(ProGenContext.getMandatoryProperty("progen.total.RPB"));
totalADF = ProGenContext.getOptionalProperty("progen.total.ADF", 0);
hline = String.format(FORMAT_S_N, calculateHline());
}
private void appendHeaders(StringBuilder line, int padding, int totalTrees, String type) {
for (int i = 0; i < totalTrees; i++) {
line.append(String.format(FORMAT_S_S, Formatter.center(String.format("%s%d", type, i), padding), CENTER_SEP));
}
}
private String calculateHline() {
final int maxLineLength = getMaxLine().length();
final StringBuilder stb = new StringBuilder(SINGLE_BLANK_SPACE);
for (int i = 2; i < maxLineLength - 1; i++) {
stb.append("-");
}
return stb.toString();
}
private void defineSecondColumnWidth() {
secondColumnWidth = Math.max(WIDTH_COLUMN, getLiterals().getString(LITERAL_GENERATION_MEAN).length());
secondColumnWidth = Math.max(secondColumnWidth, getLiterals().getString(LITERAL_BEST_RUN).length());
secondColumnWidth = Math.max(secondColumnWidth, getLiterals().getString(LITERAL_WORST_RUN).length());
}
/**
* Devuelve la línea más larga que contendrá una tabla.
*
* @return La línea más larga.
*/
private String getMaxLine() {
final StringBuilder line = new StringBuilder(LEFT_SEP);
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_INDIVIDUAL), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_GENERATION_MEAN), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_RAW), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_ADJUSTED), WIDTH_COLUMN), CENTER_SEP));
int totalTrees = 0;
totalTrees += totalRPB;
totalTrees += totalADF;
for (int i = 0; i < totalTrees; i++) {
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_NODES), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_DEPTH), WIDTH_COLUMN), CENTER_SEP));
}
return line.toString();
}
@Override
public void print() {
this.init();
final int currentGeneration = historical.getCurrentGeneration();
final int maxGenerations = ProGenContext.getOptionalProperty("progen.max-generation", Integer.MAX_VALUE);
if (currentGeneration < maxGenerations) {
printHeader(maxGenerations);
printBody();
}
this.close();
}
/**
* Imprime la tabla del mejor individuo.
*/
private void printBest() {
printBestHeaderTable();
printBestSubHeaderTable();
printBestData();
printBestTail();
}
/**
* Imprime los datos del mejor individuo.
*/
private void printBestData() {
StringBuilder line;
String ceilData;
final Individual best = (Individual) (experimentData.getPlugin(PLUGIN_NAME_BEST).getValue());
final int padding = Formatter.center(getLiterals().getString(LITERAL_INDIVIDUAL), WIDTH_COLUMN).length();
line = new StringBuilder(LEFT_SEP);
line.append(String.format(FORMAT_S, Formatter.center(SINGLE_BLANK_SPACE, padding + CENTER_SEP.length())));
line.append(String.format(FORMAT_S_S, Formatter.left(getLiterals().getString(LITERAL_INDIVIDUAL), secondColumnWidth), CENTER_SEP));
ceilData = String.format(FORMAT_3F, best.getRawFitness());
line.append(String.format(FORMAT_S_S, Formatter.right(ceilData, WIDTH_COLUMN), CENTER_SEP));
ceilData = String.format(FORMAT_5F, best.getAdjustedFitness());
line.append(String.format(FORMAT_S_S, Formatter.right(ceilData, WIDTH_COLUMN), CENTER_SEP));
printDataRPB(line, best);
printDataADF(line, best);
getWriter().printf(FORMAT_S_N_S, line.toString(), hline);
}
/**
* Imprime la cabecera de la tabla del mejor individuo.
*/
private void printBestHeaderTable() {
final StringBuilder line = new StringBuilder(LEFT_SEP);
int padding;
line.append(String.format(FORMAT_S_S, Formatter.left(getLiterals().getString("newBestIndividual"), firstColumnWidth + secondColumnWidth), CENTER_SEP));
padding = Formatter.center(getLiterals().getString(LITERAL_RAW), WIDTH_COLUMN).length();
padding += Formatter.center(getLiterals().getString(LITERAL_ADJUSTED), WIDTH_COLUMN).length() + EXTRA_PADDING;
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_FITNESS), padding), CENTER_SEP));
padding = Formatter.center(getLiterals().getString(LITERAL_NODES), WIDTH_COLUMN).length();
padding += Formatter.center(getLiterals().getString(LITERAL_DEPTH), WIDTH_COLUMN).length() + EXTRA_PADDING;
appendHeaders(line, padding, totalRPB, LITERAL_RBP);
appendHeaders(line, padding, totalADF, LITERAL_ADF);
getWriter().printf(FORMAT_S_N_S, line.toString(), hline);
}
/**
* Imprime la cabecera de la tabla de mejor individuo.
*/
private void printBestSubHeaderTable() {
printIndividualSubHeaderTable();
}
/**
* Imprime los datos resumen del mejor individuo.
*/
private void printBestTail() {
final StringBuilder stb = new StringBuilder();
final Individual best = (Individual) (experimentData.getPlugin(PLUGIN_NAME_BEST).getValue());
for (int i = 0; i < best.getTotalRPB(); i++) {
stb.append(String.format(FORMAT_S_D_N, LITERAL_RBP, i));
stb.append(Formatter.tree(best.getTrees().get(LITERAL_RBP + i)));
stb.append(String.format(FORMAT_N));
}
for (int i = 0; i < best.getTotalADF(); i++) {
stb.append(String.format(FORMAT_S_D_N, LITERAL_ADF, i));
stb.append(Formatter.tree(best.getTrees().get(LITERAL_ADF + i)));
stb.append(String.format(FORMAT_N));
}
getWriter().println(stb.toString());
}
private void printBody() {
final Individual bestTotal = (Individual) (historical.getDataCollectorExperiment(EXPERIMENT_INDIVIDUAL_DATA).getPlugin(PLUGIN_NAME_BEST).getValue());
final Individual bestGeneration = (Individual) (historical.getCurrentDataCollector(EXPERIMENT_INDIVIDUAL_DATA).getPlugin(PLUGIN_NAME_BEST).getValue());
printIndividual();
printTime();
if (bestTotal.equals(bestGeneration)) {
printBest();
}
}
private void printDataADF(StringBuilder line, Individual individual) {
for (int i = 0; i < totalADF; i++) {
line.append(String.format(FORMAT_S_S, Formatter.center(Integer.valueOf(individual.getTrees().get(LITERAL_ADF + i).getRoot().getTotalNodes()), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(Integer.valueOf(individual.getTrees().get(LITERAL_ADF + i).getRoot().getMaximunDepth()), WIDTH_COLUMN), CENTER_SEP));
}
}
private void printDataRPB(StringBuilder line, Individual individual) {
for (int i = 0; i < totalRPB; i++) {
line.append(String.format(FORMAT_S_S, Formatter.center(Integer.valueOf(individual.getTrees().get(LITERAL_RBP + i).getRoot().getTotalNodes()), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(Integer.valueOf(individual.getTrees().get(LITERAL_RBP + i).getRoot().getMaximunDepth()), WIDTH_COLUMN), CENTER_SEP));
}
}
/**
* Imprime la cabecera de la tabla de resultados.
*/
private void printHeader(int maxGenerations) {
final String generation = String.format(FORMAT_S_S,getLiterals().getString("generation"), Formatter.right(historical.getCurrentGeneration(), maxGenerations));
getWriter().printf("%n%n%s", hline);
getWriter().printf("%s%s%s%n", LEFT_SEP, Formatter.center(generation, getMaxLine().length() - LEFT_SEP.length() - RIGHT_SEP.length()), RIGHT_SEP);
getWriter().printf(FORMAT_S, hline);
}
/**
* Imprime un individuo.
*/
private void printIndividual() {
printIndividualHeaderTable();
printIndividualSubHeaderTable();
printIndividualData();
}
/**
* Imprime los datos de la mejor ejecución de un individuo.
*/
private void printIndividualBestRunData() {
StringBuilder line;
String ceilData;
final Individual best = (Individual) (experimentData.getPlugin(PLUGIN_NAME_BEST).getValue());
final int padding = Formatter.center(getLiterals().getString(LITERAL_INDIVIDUAL), WIDTH_COLUMN).length();
line = new StringBuilder(LEFT_SEP);
line.append(String.format(FORMAT_S, Formatter.center(SINGLE_BLANK_SPACE, padding + CENTER_SEP.length())));
line.append(String.format(FORMAT_S_S, Formatter.left(getLiterals().getString(LITERAL_BEST_RUN), secondColumnWidth), CENTER_SEP));
ceilData = String.format(FORMAT_3F, best.getRawFitness());
line.append(String.format(FORMAT_S_S, Formatter.right(ceilData, WIDTH_COLUMN), CENTER_SEP));
ceilData = String.format(FORMAT_5F, best.getAdjustedFitness());
line.append(String.format(FORMAT_S_S, Formatter.right(ceilData, WIDTH_COLUMN), CENTER_SEP));
printDataRPB(line, best);
printDataADF(line, best);
getWriter().println(line.toString());
}
/**
* Imprime los datos de un individuo.
*/
private void printIndividualData() {
printIndividualBestRunData();
printIndividualGenerationMeanData();
printIndividualWorstData();
}
/**
* Imprime los datos de la generación media.
*/
@SuppressWarnings("unchecked")
private void printIndividualGenerationMeanData() {
StringBuilder line;
String ceilData;
final DataCollector populationData = historical.getCurrentDataCollector("PopulationData");
final Map<String, Mean> mean = (Map<String, Mean>) (populationData.getPlugin("individualMean").getValue());
final int padding = Formatter.center(getLiterals().getString(LITERAL_INDIVIDUAL), WIDTH_COLUMN).length();
line = new StringBuilder(LEFT_SEP);
line.append(String.format(FORMAT_S, Formatter.center(SINGLE_BLANK_SPACE, padding + CENTER_SEP.length())));
line.append(String.format(FORMAT_S_S, Formatter.left(getLiterals().getString(LITERAL_GENERATION_MEAN), secondColumnWidth), CENTER_SEP));
ceilData = String.format(FORMAT_3G, mean.get(LITERAL_RAW).getValue());
line.append(String.format(FORMAT_S_S, Formatter.right(ceilData, WIDTH_COLUMN), CENTER_SEP));
ceilData = String.format(FORMAT_5F, mean.get(LITERAL_ADJUSTED).getValue());
line.append(String.format(FORMAT_S_S, Formatter.right(ceilData, WIDTH_COLUMN), CENTER_SEP));
printIndividualGenerationMeanDataTree(line, mean, totalRPB, "RPB");
printIndividualGenerationMeanDataTree(line, mean, totalADF, LITERAL_ADF);
getWriter().println(line.toString());
}
private void printIndividualGenerationMeanDataTree(StringBuilder line, final Map<String, Mean> mean, int totalTrees, String treeType) {
for (int i = 0; i < totalTrees; i++) {
line.append(String.format(FORMAT_S_S, Formatter.center(mean.get(treeType + i + "-nodes").getValue().toString(), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(mean.get(treeType + i + "-depth").getValue().toString(), WIDTH_COLUMN), CENTER_SEP));
}
}
/**
* Imprime la cabecera de la tabla de individuos.
*/
private void printIndividualHeaderTable() {
// Print head table
final StringBuilder line = new StringBuilder(LEFT_SEP);
int padding;
firstColumnWidth = WIDTH_COLUMN + CENTER_SEP.length();
defineSecondColumnWidth();
line.append(String.format(FORMAT_S_S, Formatter.left(getLiterals().getString(LITERAL_INDIVIDUAL), firstColumnWidth + secondColumnWidth), CENTER_SEP));
padding = Formatter.center(getLiterals().getString(LITERAL_RAW), WIDTH_COLUMN).length();
padding += Formatter.center(getLiterals().getString(LITERAL_ADJUSTED), WIDTH_COLUMN).length() + EXTRA_PADDING;
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_FITNESS), padding), CENTER_SEP));
padding = Formatter.center(getLiterals().getString(LITERAL_NODES), WIDTH_COLUMN).length();
padding += Formatter.center(getLiterals().getString(LITERAL_DEPTH), WIDTH_COLUMN).length() + EXTRA_PADDING;
appendHeaders(line, padding, totalRPB, LITERAL_RBP);
appendHeaders(line, padding, totalADF, LITERAL_ADF);
getWriter().printf(FORMAT_S_N_S, line.toString(), hline);
}
/**
* Imprime la cabecera de la subtabla de individuos.
*/
private void printIndividualSubHeaderTable() {
// Print sub-head table
final StringBuilder line = new StringBuilder(LEFT_SEP);
final int padding = Formatter.center(getLiterals().getString(LITERAL_INDIVIDUAL), WIDTH_COLUMN).length();
line.append(String.format("%s %s", Formatter.center(SINGLE_BLANK_SPACE, padding + secondColumnWidth), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_RAW), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_ADJUSTED), WIDTH_COLUMN), CENTER_SEP));
for (int i = 0; i < totalRPB; i++) {
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_NODES), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_DEPTH), WIDTH_COLUMN), CENTER_SEP));
}
for (int i = 0; i < totalADF; i++) {
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_NODES), WIDTH_COLUMN), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString(LITERAL_DEPTH), WIDTH_COLUMN), CENTER_SEP));
}
getWriter().printf(FORMAT_S_N, line.toString());
}
/**
* Imprime los datos del peor individuo.
*/
private void printIndividualWorstData() {
StringBuilder line;
String ceilData;
final Individual worst = (Individual) (historical.getCurrentDataCollector(EXPERIMENT_INDIVIDUAL_DATA).getPlugin("worst").getValue());
final int padding = Formatter.center(getLiterals().getString(LITERAL_INDIVIDUAL), WIDTH_COLUMN).length();
line = new StringBuilder(LEFT_SEP);
line.append(String.format(FORMAT_S, Formatter.center(SINGLE_BLANK_SPACE, padding + CENTER_SEP.length())));
line.append(String.format(FORMAT_S_S, Formatter.left(getLiterals().getString(LITERAL_WORST_RUN), secondColumnWidth), CENTER_SEP));
ceilData = String.format(FORMAT_3G, worst.getRawFitness());
line.append(String.format(FORMAT_S_S, Formatter.right(ceilData, WIDTH_COLUMN), CENTER_SEP));
ceilData = String.format(FORMAT_5F, worst.getAdjustedFitness());
line.append(String.format(FORMAT_S_S, Formatter.right(ceilData, WIDTH_COLUMN), CENTER_SEP));
printDataRPB(line, worst);
printDataADF(line, worst);
getWriter().printf(FORMAT_S_N_S, line.toString(), hline);
}
/**
* Imprime la tabla de tiempos.
*/
private void printTime() {
printTimeHeaderTable();
printTimeData();
}
/**
* Imprime los tiempos de ejecución de individuos.
*/
private void printTimeBreeding() {
final StringBuilder line = new StringBuilder(LEFT_SEP);
int padding = hline.length() - (firstColumnWidth + secondColumnWidth) - 2 * CENTER_SEP.length() - EXTRA_PADDING;
padding = padding / 2;
final Plugin breeding = historical.getCurrentDataCollector(DATACOLLECTOR_POPULATION_TIME_DATA).getPlugin(PLUGIN_NAME_BREEDING);
String ceilData;
line.append(String.format(FORMAT_S, Formatter.center(SINGLE_BLANK_SPACE, firstColumnWidth)));
line.append(String.format(FORMAT_S_S, Formatter.left(getLiterals().getString(LITERAL_BREEDING), secondColumnWidth), CENTER_SEP));
ceilData = String.format(FORMAT_S, breeding.getPlugin(PLUGIN_NAME_MEAN).getValue().toString());
line.append(String.format(FORMAT_S_S, Formatter.center(ceilData, padding), CENTER_SEP));
ceilData = String.format(FORMAT_S, breeding.getPlugin(PLUGIN_NAME_TOTAL).getValue().toString());
line.append(String.format(FORMAT_S_S, Formatter.center(ceilData, padding), CENTER_SEP));
getWriter().printf(FORMAT_S_N, line.toString());
}
/**
* Imprime los datos de la tabla de tiempos.
*/
private void printTimeData() {
printTimeBreeding();
printTimeEvaluation();
}
/**
* Imprime los tiempos de evaluación de individuos.
*/
private void printTimeEvaluation() {
final StringBuilder line = new StringBuilder(LEFT_SEP);
int padding = hline.length() - (firstColumnWidth + secondColumnWidth) - 2 * CENTER_SEP.length() - EXTRA_PADDING;
padding = padding / 2;
final Plugin evaluation = historical.getCurrentDataCollector(DATACOLLECTOR_POPULATION_TIME_DATA).getPlugin(PLUGIN_NAME_EVALUATION);
String ceilData;
line.append(String.format(FORMAT_S, Formatter.center(SINGLE_BLANK_SPACE, firstColumnWidth)));
line.append(String.format(FORMAT_S_S, Formatter.left(getLiterals().getString(LITERAL_EVALUATION), secondColumnWidth), CENTER_SEP));
ceilData = String.format(FORMAT_S, evaluation.getPlugin(PLUGIN_NAME_MEAN).getValue().toString());
line.append(String.format(FORMAT_S_S, Formatter.center(ceilData, padding), CENTER_SEP));
ceilData = String.format(FORMAT_S, evaluation.getPlugin(PLUGIN_NAME_TOTAL).getValue().toString());
line.append(String.format(FORMAT_S_S, Formatter.center(ceilData, padding), CENTER_SEP));
getWriter().printf(FORMAT_S_N_S, line.toString(), hline);
}
/**
* Imprime la cabecera de la tabla de tiempos.
*/
private void printTimeHeaderTable() {
final StringBuilder line = new StringBuilder(LEFT_SEP);
int padding;
line.append(String.format(FORMAT_S_S, Formatter.left(getLiterals().getString("time"), firstColumnWidth + secondColumnWidth), CENTER_SEP));
padding = hline.length() - (firstColumnWidth + secondColumnWidth) - 2 * CENTER_SEP.length() - EXTRA_PADDING;
padding = padding / 2;
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString("populationMean"), padding), CENTER_SEP));
line.append(String.format(FORMAT_S_S, Formatter.center(getLiterals().getString("totalPopulation"), padding), CENTER_SEP));
getWriter().printf(FORMAT_S_N_S, line.toString(), hline);
}
}