/// <summary>
        /// Fungsi Virtual unutk mendapatkan turunan pertama pada fungsi 
        /// </summary>
        /// <param name="input">Vector. Vector parameter yang dimasukkan</param>
        /// <returns>double. hasil penghitungan fungsi sesuai nilai masukkannya</returns>
        public virtual Vector Gradient(Vector input)
        {
            Vector result = new Vector(input.Tuples);
            Vector vh = new Vector(input.Tuples);
            double h = 0.000001;

            for (int i = 0; i < input.Tuples; i++)
            {
                vh.InitializeAllValue(0);
                vh[i] = h;

                result[i] = (this.Function(input + vh) - this.Function(input)) / h;
            }

            return result;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Fungsi untuk pencarian nilai optimum metode Quasi Newton dengan algoritma DFP
        /// Diperkenalkan oleh Davidon, Fletcher dan Powell, sehingga sering dikenal dengan sebutan DFP Algorithm
        /// </summary>
        /// <returns>Vector. Nilai parameter optimum</returns>
        public Vector DFPOptimize()
        {
            double previousFunction = double.MaxValue;
            double currentFunction = double.MaxValue;

            Matrix H;
            Vector x, x1, lastX, s, g, gamma, delta;
            double alpha, sTg, error;

            this.iteration = 0;

            // iterasi 0, inisialisasi,
            // x diinisialisasi dengan initial point, H (hessian) dinisialisasi dengan matrix identitas
            x = this.initialPoint;
            H = this.hessian;

            Vector nullVector = new Vector(x.Tuples);
            nullVector.InitializeAllValue(0);

            do
            {
                iteration++;

                previousFunction = this.function.Function(x);
                lastX = x;

                //g = gradient/turunan pertama fungsi
                g = this.function.Gradient(x);
                // s = search direction
                s = -1 * (H * g);
                // normalisasi pada nilai s
                s = (1 / s.Length) * s;

                // stg = nilai s transpose dikalikan dengan g (gradient),
                // untuk digunakan pada pencarian nilai alpha
                sTg = Vector.DoubleMultiply(s.GetTranspose(), g);
                // Alpha = nilai unutk memaksimumkan fungsi f(x + alpha s)
                // dicari dengan algoritma "Fletcher Acceptability Criterion"
                // Sumber, buku "Numerical Methods And Analysis" karya Buchanan and Turner
                alpha = this.findAcceptableAlpha(x, s, sTg);

                if (alpha == 0) break;

                double alphaTemp = alpha;
                do
                {
                    alpha = alphaTemp;
                    delta = alpha * s;
                    x1 = x + delta;

                    // Perlakuan khusus ketika fungsi yang dihasilkan dari nilai alpha bernilai NaN
                    // alpha dipindahkan 0.95 kali alpha sebelumnya
                    alphaTemp = 0.95 * alpha;
                } while (double.IsNaN(this.function.Function(x1)));

                delta = alpha * s;
                x1 = x + delta;
                gamma = this.function.Gradient(x1) - g;
                x = x1;
                currentFunction = this.function.Function(x);

                // meng-update nilai Hessian baru dengan algoritma BFGS
                Vector Hy = H * gamma;
                Matrix M = (1 / (Vector.DoubleMultiply(gamma.GetTranspose(), Hy))) * (Vector.MatrixMultiply(Hy, Hy.GetTranspose()));
                Matrix N = (1 / (Vector.DoubleMultiply(delta.GetTranspose(), gamma))) * (Vector.MatrixMultiply(delta, delta.GetTranspose()));

                H = H - M + N;

                g = this.function.Gradient(x);

                // error = selisih nilai fungsi sekarang dengan fungsi sebelumnya
                error = Math.Abs(currentFunction - previousFunction);

            } while (error > this.functolerance && g.Length > this.gradtolerance && g != nullVector && iteration < maximumIteration && (currentFunction - previousFunction) < this.tolerance);

            // Kondisi ketika fungsi semakin menaik/membesar
            if (currentFunction - previousFunction > 0)
            {
                this.optimumValue = Math.Min(currentFunction, previousFunction);
                x = lastX;
                this.isConvergence = false;

            }
            // Kondisi ketika fungsi yang dihasilkan bernilai NaN
            else if (double.IsNaN(currentFunction))
            {
                this.optimumValue = previousFunction;
                x = lastX;
                this.isConvergence = false;
            }
            // Kondisi ketika fungsi mencapai kekonvergenan
            else
            {
                this.optimumValue = currentFunction;
                this.isConvergence = true;
            }

            return x;
        }