/// <summary>
        /// Learns a model that can map the given inputs to the desired outputs.
        /// </summary>
        /// <param name="x">The model inputs.</param>
        /// <param name="weights">The weight of importance for each input sample.</param>
        /// <returns>
        /// A model that has learned how to produce suitable outputs
        /// given the input data <paramref name="x" />.
        /// </returns>
        public MultivariateLinearRegression Learn(double[][] x, double[] weights = null)
        {
            if (weights != null)
            {
                throw new ArgumentException(Accord.Properties.Resources.NotSupportedWeights, "weights");
            }

            // Calculate common measures to speedup other calculations
            this.columnMeans  = Measures.Mean(x, dimension: 0);
            this.columnStdDev = Measures.StandardDeviation(x, columnMeans);

            NumberOfInputs = x.Columns();
            if (NumberOfOutputs == 0)
            {
                NumberOfOutputs = NumberOfInputs;
            }

            // First, the data should be centered by subtracting
            //  the mean of each column in the source data matrix.
            var matrix = Adjust(x, overwriteSourceMatrix);

            // Pre-process the centered data matrix to have unit variance
            var whiten = Statistics.Tools.Whitening(matrix, out whiteningMatrix);

            // Generate a new unitary initial guess for the de-mixing matrix
            var initial = Jagged.Random(NumberOfOutputs, matrix.Columns());


            // Compute the demixing matrix using the selected algorithm
            if (algorithm == IndependentComponentAlgorithm.Deflation)
            {
                revertMatrix = deflation(whiten, NumberOfOutputs, initial);
            }
            else // if (algorithm == IndependentComponentAlgorithm.Parallel)
            {
                revertMatrix = parallel(whiten, NumberOfOutputs, initial);
            }

            // Combine the rotation and demixing matrices
            revertMatrix = whiteningMatrix.DotWithTransposed(revertMatrix);
            revertMatrix.Divide(revertMatrix.Sum(), result: revertMatrix);

            // Compute the original source mixing matrix
            mixingMatrix = Matrix.PseudoInverse(revertMatrix);
            mixingMatrix.Divide(mixingMatrix.Sum(), result: mixingMatrix);

            this.demix = createRegression(revertMatrix, columnMeans, columnStdDev, analysisMethod);
            this.mix   = demix.Inverse();

            // Creates the object-oriented structure to hold the principal components
            var array = new IndependentComponent[NumberOfOutputs];

            for (int i = 0; i < array.Length; i++)
            {
                array[i] = new IndependentComponent(this, i);
            }
            this.componentCollection = new IndependentComponentCollection(array);

            return(demix);
        }
        public void Compute(int components)
        {
            NumberOfOutputs = components;

            // First, the data should be centered by subtracting
            //  the mean of each column in the source data matrix.
            double[][] matrix = Adjust(sourceMatrix.ToJagged(), overwriteSourceMatrix);

            // Pre-process the centered data matrix to have unit variance
            double[][] whiten = Statistics.Tools.Whitening(matrix, out whiteningMatrix);

            // Generate a new unitary initial guess for the de-mixing matrix
            double[][] initial = Jagged.Random(components, matrix.Columns());


            // Compute the demixing matrix using the selected algorithm
            if (algorithm == IndependentComponentAlgorithm.Deflation)
            {
                revertMatrix = deflation(whiten, components, initial);
            }
            else // if (algorithm == IndependentComponentAlgorithm.Parallel)
            {
                revertMatrix = parallel(whiten, components, initial);
            }

            // Combine the rotation and demixing matrices
            revertMatrix = whiteningMatrix.DotWithTransposed(revertMatrix);
            revertMatrix.Divide(revertMatrix.Sum(), result: revertMatrix);

            // Compute the original source mixing matrix
            mixingMatrix = Matrix.PseudoInverse(revertMatrix);
            mixingMatrix.Divide(mixingMatrix.Sum(), result: mixingMatrix);

            // Demix the data into independent components
            resultMatrix = Matrix.Dot(matrix, revertMatrix).ToMatrix();

            this.demix = createRegression(revertMatrix, columnMeans, columnStdDev, analysisMethod);
            this.mix   = demix.Inverse();

            // Creates the object-oriented structure to hold the principal components
            var array = new IndependentComponent[components];

            for (int i = 0; i < array.Length; i++)
            {
                array[i] = new IndependentComponent(this, i);
            }
            this.componentCollection = new IndependentComponentCollection(array);
        }
        /// <summary>
        ///   Computes the Independent Component Analysis algorithm.
        /// </summary>
        ///
        public void Compute(int components)
        {
            // First, the data should be centered by subtracting
            //  the mean of each column in the source data matrix.
            double[,] matrix = Adjust(sourceMatrix, overwriteSourceMatrix);

            // Pre-process the centered data matrix to have unit variance
            double[,] whiten = Statistics.Tools.Whitening(matrix, out whiteningMatrix);

            // Generate a new unitary initial guess for the de-mixing matrix
            double[,] initial = Matrix.Random(components, matrix.GetLength(1), 0, 1);


            // Compute the demixing matrix using the selected algorithm
            if (algorithm == IndependentComponentAlgorithm.Deflation)
            {
                revertMatrix = deflation(whiten, components, initial);
            }
            else // if (algorithm == IndependentComponentAlgorithm.Parallel)
            {
                revertMatrix = parallel(whiten, components, initial);
            }



            // Combine the rotation and demixing matrices
            revertMatrix = whiteningMatrix.MultiplyByTranspose(revertMatrix);
            normalize(revertMatrix);

            // Compute the original source mixing matrix
            mixingMatrix = Matrix.PseudoInverse(revertMatrix);
            normalize(mixingMatrix);

            // Demix the data into independent components
            resultMatrix = matrix.Multiply(revertMatrix);


            // Creates the object-oriented structure to hold the principal components
            var array = new IndependentComponent[components];

            for (int i = 0; i < array.Length; i++)
            {
                array[i] = new IndependentComponent(this, i);
            }
            this.componentCollection = new IndependentComponentCollection(array);
        }