/*
 * Encog(tm) Core v2.5 
 * http://www.heatonresearch.com/encog/
 * http://code.google.com/p/encog-java/
 * 
 * Copyright 2008-2010 by Heaton Research Inc.
 * 
 * Released under the LGPL.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 * 
 * Encog and Heaton Research are Trademarks of Heaton Research, Inc.
 * For information on Heaton Research trademarks, visit:
 * 
 * http://www.heatonresearch.com/copyright.html
 */

package org.encog.neural.networks.training.simple;

import org.encog.engine.util.ErrorCalculation;
import org.encog.neural.NeuralNetworkError;
import org.encog.neural.data.NeuralData;
import org.encog.neural.data.NeuralDataPair;
import org.encog.neural.data.NeuralDataSet;
import org.encog.neural.networks.BasicNetwork;
import org.encog.neural.networks.layers.Layer;
import org.encog.neural.networks.synapse.Synapse;
import org.encog.neural.networks.training.BasicTraining;
import org.encog.neural.networks.training.LearningRate;

/**
 * Train an ADALINE neural network.
 */
public class TrainAdaline extends BasicTraining implements LearningRate {

	/**
	 * The network to train.
	 */
	private final BasicNetwork network;

	/**
	 * The synapse to train.
	 */
	private final Synapse synapse;

	/**
	 * The training data to use.
	 */
	private final NeuralDataSet training;

	/**
	 * The learning rate.
	 */
	private double learningRate;

	/**
	 * Construct an ADALINE trainer.
	 * 
	 * @param network
	 *            The network to train.
	 * @param training
	 *            The training data.
	 * @param learningRate
	 *            The learning rate.
	 */
	public TrainAdaline(final BasicNetwork network,
			final NeuralDataSet training, final double learningRate) {
		if (network.getStructure().getLayers().size() > 2) {
			throw new NeuralNetworkError(
					"An ADALINE network only has two layers.");
		}
		this.network = network;

		final Layer input = network.getLayer(BasicNetwork.TAG_INPUT);

		this.synapse = input.getNext().get(0);
		this.training = training;
		this.learningRate = learningRate;
	}

	/**
	 * @return The learning rate.
	 */
	public double getLearningRate() {
		return this.learningRate;
	}

	/**
	 * @return The network being trained.
	 */
	public BasicNetwork getNetwork() {
		return this.network;
	}

	/**
	 * Perform a training iteration.
	 */
	public void iteration() {

		final ErrorCalculation errorCalculation = new ErrorCalculation();

		final Layer inputLayer = this.network.getLayer(BasicNetwork.TAG_INPUT);
		final Layer outputLayer = this.network
				.getLayer(BasicNetwork.TAG_OUTPUT);

		for (final NeuralDataPair pair : this.training) {
			// calculate the error
			final NeuralData output = this.network.compute(pair.getInput());

			for (int currentAdaline = 0; currentAdaline < output.size(); 
				currentAdaline++) {
				final double diff = pair.getIdeal().getData(currentAdaline)
						- output.getData(currentAdaline);

				// weights
				for (int i = 0; i < inputLayer.getNeuronCount(); i++) {
					final double input = pair.getInput().getData(i);
					this.synapse.getMatrix().add(i, currentAdaline,
							this.learningRate * diff * input);
				}

				// bias
				double t = outputLayer.getBiasWeight(currentAdaline);
				t += this.learningRate * diff;
				outputLayer.setBiasWeight(currentAdaline, t);
			}

			errorCalculation.updateError(output.getData(), pair.getIdeal().getData());
		}

		// set the global error
		setError(errorCalculation.calculate());
	}

	/**
	 * Set the learning rate.
	 * 
	 * @param rate
	 *            The new learning rate.
	 */
	public void setLearningRate(final double rate) {
		this.learningRate = rate;
	}

}

@@ -1548,24 +1548,86 @@
 ers.Layer;%0D%0A
+import org.encog.neural.networks.structure.FlatUpdateNeeded;%0D%0A
 import org.e
@@ -4198,24 +4198,102 @@
 , t);%0D%0A%09%09%09%7D%0D
+%0A%09%09%09%0D%0A%09%09%09this.network.getStructure().setFlatUpdate(FlatUpdateNeeded.Flatten);%0D
 %0A%0D%0A%09%09%09errorC

Update adaline for flat network.