/* * 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; import java.io.File; import java.util.Date; import org.encog.Encog; import org.encog.app.analyst.EncogAnalyst; import org.encog.app.analyst.script.prop.ScriptProperties; import org.encog.app.generate.generators.LanguageSpecificGenerator; import org.encog.app.generate.generators.ProgramGenerator; import org.encog.app.generate.generators.TemplateGenerator; import org.encog.app.generate.generators.cs.GenerateCS; import org.encog.app.generate.generators.java.GenerateEncogJava; import org.encog.app.generate.generators.js.GenerateEncogJavaScript; import org.encog.app.generate.generators.mql4.GenerateMQL4; import org.encog.app.generate.generators.ninja.GenerateNinjaScript; import org.encog.app.generate.program.EncogGenProgram; import org.encog.app.generate.program.EncogProgramNode; import org.encog.ml.MLEncodable; import org.encog.ml.MLMethod; import org.encog.neural.networks.BasicNetwork; import org.encog.persist.EncogDirectoryPersistence; /** * Perform Encog code generation. Encog is capable of generating code from * several different objects. This code generation will be to the specified * target language. */ public class EncogCodeGeneration { /** * Is the specified method supported for code generation? * * @param method * The specified method. * @return True, if the specified method is supported. */ public static boolean isSupported(final MLMethod method) { if (method instanceof BasicNetwork) { return true; } else { return false; } } /** * The target language for the code generation. */ private final TargetLanguage targetLanguage; /** * True if the data should be embedded. */ private boolean embedData; /** * The language specific code generator. */ private LanguageSpecificGenerator generator; /** * The program that we are generating. */ private final EncogGenProgram program = new EncogGenProgram(); /** * Construct the generation object. * * @param theTargetLanguage * The target language. */ public EncogCodeGeneration(final TargetLanguage theTargetLanguage) { this.targetLanguage = theTargetLanguage; switch (theTargetLanguage) { case NoGeneration: throw new AnalystCodeGenerationError( "No target language has been specified for code generation."); case Java: this.generator = new GenerateEncogJava(); break; case CSharp: this.generator = new GenerateCS(); break; case MQL4: this.generator = new GenerateMQL4(); break; case NinjaScript: this.generator = new GenerateNinjaScript(); break; case JavaScript: this.generator = new GenerateEncogJavaScript(); break; } } /** * Generate the code from Encog Analyst. * * @param analyst * The Encog Analyst object to use for code generation. */ public void generate(final EncogAnalyst analyst) { if (this.targetLanguage == TargetLanguage.MQL4 || this.targetLanguage == TargetLanguage.NinjaScript) { if (!this.embedData) { throw new AnalystCodeGenerationError( "MQL4 and Ninjascript must be embedded."); } } if (this.generator instanceof ProgramGenerator) { final String methodID = analyst .getScript() .getProperties() .getPropertyString( ScriptProperties.ML_CONFIG_MACHINE_LEARNING_FILE); final String trainingID = analyst .getScript() .getProperties() .getPropertyString(ScriptProperties.ML_CONFIG_TRAINING_FILE); final File methodFile = analyst.getScript().resolveFilename( methodID); final File trainingFile = analyst.getScript().resolveFilename( trainingID); generate(methodFile, trainingFile); } else { ((TemplateGenerator) this.generator).generate(analyst); } } /** * Generate from a method and data. * * @param method * The machine learning method to generate from. * @param data * The data to use perform generation. */ public void generate(final File method, final File data) { EncogProgramNode createNetworkFunction = null; this.program.addComment("Code generated by Encog v" + Encog.getInstance().getProperties().get(Encog.ENCOG_VERSION)); this.program.addComment("Generation Date: " + new Date().toString()); this.program.addComment("Generated code may be used freely"); this.program.addComment("http://www.heatonresearch.com/encog"); final EncogProgramNode mainClass = this.program .createClass("EncogExample"); if (this.targetLanguage == TargetLanguage.MQL4 || this.targetLanguage == TargetLanguage.NinjaScript) { throw new AnalystCodeGenerationError( "MQL4 and Ninjascript can only be generated from Encog Analyst"); } if (data != null) { mainClass.embedTraining(data); if (!(this.generator instanceof GenerateEncogJavaScript)) { mainClass.generateLoadTraining(data); } } if (method != null) { createNetworkFunction = generateForMethod(mainClass, method); } final EncogProgramNode mainFunction = mainClass.createMainFunction(); if (createNetworkFunction != null) { mainFunction.createFunctionCall(createNetworkFunction, "MLMethod", "method"); } if (data != null) { if (!(this.generator instanceof GenerateEncogJavaScript)) { mainFunction.createFunctionCall("createTraining", "MLDataSet", "training"); } } mainFunction .addComment("Network and/or data is now loaded, you can add code to train, evaluate, etc."); ((ProgramGenerator) this.generator).generate(this.program, this.embedData); } /** * GEnerate from a machine learning method. * * @param mainClass * The main class. * @param method * The filename of the method. * @return The newly created node. */ private EncogProgramNode generateForMethod( final EncogProgramNode mainClass, final File method) { if (this.embedData) { final MLEncodable encodable = (MLEncodable) EncogDirectoryPersistence .loadObject(method); final double[] weights = new double[encodable.encodedArrayLength()]; encodable.encodeToArray(weights); mainClass.createArray("WEIGHTS", weights); } return mainClass.createNetworkFunction("createNetwork", method); } /** * @return the targetLanguage */ public TargetLanguage getTargetLanguage() { return this.targetLanguage; } /** * @return True, if data should be embeded. */ public boolean isEmbedData() { return this.embedData; } /** * Save the contents to a string. * * @return The contents. */ public String save() { return this.generator.getContents(); } /** * Save the contents to the specified file. * * @param file The file to save to. */ public void save(final File file) { this.generator.writeContents(file); } /** * Set if data should be embeded. * * @param embedData * True, if data should embeded. */ public void setEmbedData(final boolean embedData) { this.embedData = embedData; } }