/// <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; }
/// <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; }