/*
* Encog(tm) Core v3.4 - Java Version
* http://www.heatonresearch.com/encog/
* https://github.com/encog/encog-java-core
* Copyright 2008-2016 Heaton Research, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For more information on Heaton Research copyrights, licenses
* and trademarks visit:
* http://www.heatonresearch.com/copyright
*/
package org.encog.app.generate.generators;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import org.encog.Encog;
import org.encog.app.analyst.EncogAnalyst;
import org.encog.app.generate.AnalystCodeGenerationError;
import org.encog.engine.network.activation.ActivationElliott;
import org.encog.engine.network.activation.ActivationElliottSymmetric;
import org.encog.engine.network.activation.ActivationFunction;
import org.encog.engine.network.activation.ActivationLinear;
import org.encog.engine.network.activation.ActivationSigmoid;
import org.encog.engine.network.activation.ActivationTANH;
import org.encog.neural.flat.FlatNetwork;
import org.encog.util.EngineArray;
import org.encog.util.csv.CSVFormat;
import org.encog.util.file.ResourceInputStream;
import org.encog.util.logging.EncogLogging;
/**
* Provides a basic implementation of a template generator.
*/
public abstract class AbstractTemplateGenerator implements TemplateGenerator {
/**
* The contents of the generated file.
*/
private final StringBuilder contents = new StringBuilder();
/**
* The Encog analyst that is being used.
*/
private EncogAnalyst analyst;
/**
* The current indention level.
*/
private int indentLevel = 0;
/**
* Add a line, with proper indention.
*
* @param line
* The line to add.
*/
public void addLine(final String line) {
for (int i = 0; i < this.indentLevel; i++) {
this.contents.append("\t");
}
this.contents.append(line);
this.contents.append("\n");
}
/**
* Add a name value definition, as a double array.
*
* @param name
* The name.
* @param data
* THe data.
*/
public void addNameValue(final String name, final double[] data) {
final StringBuilder value = new StringBuilder();
if (data == null) {
value.append(name);
value.append(" = " + getNullArray() + ";");
addLine(value.toString());
} else {
toBrokenList(value, data);
addNameValue(name, "{" + value.toString() + "}");
}
}
/**
* Add a name-value as an int.
*
* @param name
* The name.
* @param value
* THe value.
*/
public void addNameValue(final String name, final int value) {
addNameValue(name, "" + value);
}
/**
* Add a name-value array where the value is an int array.
*
* @param name
* The name.
* @param data
* THe value.
*/
public void addNameValue(final String name, final int[] data) {
final StringBuilder value = new StringBuilder();
if (data == null) {
value.append(name);
value.append(" = " + getNullArray() + ";");
addLine(value.toString());
} else {
toBrokenList(value, data);
addNameValue(name, "{" + value.toString() + "}");
}
}
/**
* Add a name-value where a string is the value.
*
* @param name
* The name.
* @param value
* The value.
*/
public void addNameValue(final String name, final String value) {
final StringBuilder line = new StringBuilder();
line.append(name);
line.append(" = ");
if (value == null) {
line.append(getNullArray());
} else {
line.append(value);
}
line.append(";");
addLine(line.toString());
}
/**
* Create an array of activations based on a flat network.
*
* @param flat
* The flat network.
* @return The array of flat activations.
*/
public int[] createActivations(final FlatNetwork flat) {
final int[] result = new int[flat.getActivationFunctions().length];
for (int i = 0; i < flat.getActivationFunctions().length; i++) {
final ActivationFunction af = flat.getActivationFunctions()[i];
if (af instanceof ActivationLinear) {
result[i] = 0;
} else if (af instanceof ActivationTANH) {
result[i] = 1;
}
if (af instanceof ActivationSigmoid) {
result[i] = 2;
}
if (af instanceof ActivationElliottSymmetric) {
result[i] = 3;
}
if (af instanceof ActivationElliott) {
result[i] = 4;
}
}
return result;
}
/**
* Create an array of doubles to hold the specified flat network.
*
* @param flat
* The flat network to use as a model.
* @return The new array.
*/
public double[] createParams(final FlatNetwork flat) {
final double[] result = new double[flat.getActivationFunctions().length];
EngineArray.fill(result, 1);
return result;
}
/**
* Generate based on the provided Encog Analyst.
*
* @param theAnalyst
* The Encog analyst to base this on.
*/
@Override
public void generate(final EncogAnalyst theAnalyst) {
InputStream is = null;
BufferedReader br = null;
this.analyst = theAnalyst;
try {
is = ResourceInputStream.openResourceInputStream(getTemplatePath());
br = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = br.readLine()) != null) {
if (line.startsWith("~~")) {
processToken(line.substring(2).trim());
} else {
this.contents.append(line);
this.contents.append("\n");
}
}
br.close();
} catch (final IOException ex) {
throw new AnalystCodeGenerationError(ex);
} finally {
if (is != null) {
try {
is.close();
} catch (final IOException ex) {
EncogLogging.log(EncogLogging.LEVEL_ERROR, ex);
}
}
if (br != null) {
try {
br.close();
} catch (final IOException ex) {
EncogLogging.log(EncogLogging.LEVEL_ERROR, ex);
}
}
}
}
/**
* @return The Encog analyst that we are using.
*/
public EncogAnalyst getAnalyst() {
return this.analyst;
}
/**
* @return The generated contents.
*/
@Override
public String getContents() {
return this.contents.toString();
}
/**
* @return The current indent level.
*/
public int getIndentLevel() {
return this.indentLevel;
}
/**
* @return A platform specific array set to null.
*/
public abstract String getNullArray();
/**
* @return Get a resource path to the template that we are using.
*/
public abstract String getTemplatePath();
/**
* Indent to the right one.
*/
public void indentIn() {
this.indentLevel++;
}
/**
* Indent to the left one.
*/
public void indentOut() {
this.indentLevel--;
}
/**
* Process the specified token.
*
* @param command
* The token to process.
*/
public abstract void processToken(String command);
public void setIndentLevel(final int indentLevel) {
this.indentLevel = indentLevel;
}
/**
* Create an array list broken into 10 columns. This prevents a very large
* array from creating a very long single line.
*
* @param result
* The string builder to add to.
* @param data
* The data to convert.
*/
public void toBrokenList(final StringBuilder result, final double[] data) {
int lineCount = 0;
result.setLength(0);
for (int i = 0; i < data.length; i++) {
if (i != 0) {
result.append(',');
}
lineCount++;
if (lineCount > 10) {
result.append("\n");
lineCount = 0;
}
result.append(CSVFormat.EG_FORMAT.format(data[i],
Encog.DEFAULT_PRECISION));
}
}
/**
* Create an array list broken into 10 columns. This prevents a very large
* array from creating a very long single line.
*
* @param result
* The string builder to add to.
* @param data
* The data to convert.
*/
public void toBrokenList(final StringBuilder result, final int[] data) {
int lineCount = 0;
for (int i = 0; i < data.length; i++) {
if (i != 0) {
result.append(',');
}
lineCount++;
if (lineCount > 10) {
result.append("\n");
lineCount = 0;
}
result.append("" + data[i]);
}
}
/**
* {@inheritDoc}
*/
@Override
public void writeContents(final File targetFile) {
try {
final FileWriter outFile = new FileWriter(targetFile);
final PrintWriter out = new PrintWriter(outFile);
out.print(this.contents.toString());
out.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
}