content: package aima.core.learning.neural;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import aima.core.util.math.Matrix;
  import aima.core.util.math.Vector;
  
  /**
   * @author Ravi Mohan
   * 
   */
  public class LayerSensitivity {
  	/*
  	 * contains sensitivity matrices and related calculations for each layer.
  	 * Used for backprop learning
  	 */
  
  	private Matrix sensitivityMatrix;
  	private final Layer layer;
  
  	public LayerSensitivity(Layer layer) {
  		Matrix weightMatrix = layer.getWeightMatrix();
  		this.sensitivityMatrix = new Matrix(weightMatrix.getRowDimension(),
  				weightMatrix.getColumnDimension());
  		this.layer = layer;
  
  	}
  
  	public Matrix getSensitivityMatrix() {
  		return sensitivityMatrix;
  	}
  
  	public Matrix sensitivityMatrixFromErrorMatrix(Vector errorVector) {
  		Matrix derivativeMatrix = createDerivativeMatrix(layer
  				.getLastInducedField());
  		Matrix calculatedSensitivityMatrix = derivativeMatrix
  				.times(errorVector).times(-2.0);
  		sensitivityMatrix = calculatedSensitivityMatrix.copy();
  		return calculatedSensitivityMatrix;
  	}
  
  	public Matrix sensitivityMatrixFromSucceedingLayer(
  			LayerSensitivity nextLayerSensitivity) {
  		Layer nextLayer = nextLayerSensitivity.getLayer();
  		Matrix derivativeMatrix = createDerivativeMatrix(layer
  				.getLastInducedField());
  		Matrix weightTranspose = nextLayer.getWeightMatrix().transpose();
  		Matrix calculatedSensitivityMatrix = derivativeMatrix.times(
  				weightTranspose).times(
  				nextLayerSensitivity.getSensitivityMatrix());
  		sensitivityMatrix = calculatedSensitivityMatrix.copy();
  		return sensitivityMatrix;
  	}
  
  	public Layer getLayer() {
  		return layer;
  	}
  
  	//
  	// PRIVATE METHODS
  	//
  
  	private Matrix createDerivativeMatrix(Vector lastInducedField) {
  		List<Double> lst = new ArrayList<>();
  		for (int i = 0; i < lastInducedField.size(); i++) {
  			lst.add(layer.getActivationFunction().deriv(lastInducedField.getValue(i)));
  		}
  		return Matrix.createDiagonalMatrix(lst);
  	}
  }
  