【C言語】数値的最適化の実装

【C言語】数値的最適化の実装

目次

数値的最適化とは

数値的最適化とは、関数の最小値や最大値を求めるアルゴリズムのことを指します。 解析的に解くことが難しい問題に対して、数値的な手法を用いて最適解を近似的に求めます。 最適化手法は、大きく「導関数を用いる方法」と「導関数を用いない方法」に分類されます。 本記事では、C言語を用いて代表的な最適化手法を実装する方法を解説します。

勾配降下法

勾配降下法は、最適化問題において最も基本的な手法の一つです。 目的関数 \( f(x) \) の勾配(微分)を利用し、少しずつ最小値へと近づいていきます。 一般的な更新式は次のように表されます:

\[ x_{k+1} = x_k – \alpha \nabla f(x_k) \]

ここで、\(\alpha\) は学習率(ステップサイズ)です。

実装例

#include <stdio.h>
#include <math.h>

double f(double x) {
    return x * x - 4 * x + 4;  // (x-2)^2 の最小値は x=2
}

double df(double x) {
    return 2 * x - 4;  // f(x) の導関数
}

void gradient_descent(double x0, double alpha, int iterations) {
    double x = x0;
    for (int i = 0; i < iterations; i++) {
        x = x - alpha * df(x);
        printf("Iteration %d: x = %f, f(x) = %f\n", i, x, f(x));
    }
}

int main() {
    gradient_descent(0.0, 0.1, 10);
    return 0;
}

ニュートン法

ニュートン法は、関数の2階微分(ヘッセ行列)を利用して収束を早める手法です。 更新式は次のようになります:

\[ x_{k+1} = x_k - \frac{\nabla f(x_k)}{\nabla^2 f(x_k)} \]

実装例

#include <stdio.h>
#include <math.h>

double f(double x) {
    return x * x - 4 * x + 4;
}

double df(double x) {
    return 2 * x - 4;
}

double ddf(double x) {
    return 2;
}

void newton_method(double x0, int iterations) {
    double x = x0;
    for (int i = 0; i < iterations; i++) {
        x = x - df(x) / ddf(x);
        printf("Iteration %d: x = %f, f(x) = %f\n", i, x, f(x));
    }
}

int main() {
    newton_method(0.0, 5);
    return 0;
}

準ニュートン法

準ニュートン法は、ニュートン法のヘッセ行列を直接求めずに近似する手法です。 代表的なものに BFGS 法があります。

BFGS 法の概要

BFGS 法では、逆ヘッセ行列 \( H_k \) を更新していきます:

\[ H_{k+1} = H_k + \frac{y_k y_k^T}{y_k^T s_k} - \frac{H_k s_k s_k^T H_k}{s_k^T H_k s_k} \]

制約付き最適化

制約付き最適化では、制約条件を満たしながら最適解を求める必要があります。 代表的な手法として「ラグランジュ乗数法」「投影勾配法」「内点法」などがあります。

投影勾配法の実装

#include <stdio.h>
#include <math.h>

double f(double x) {
    return x * x;
}

double df(double x) {
    return 2 * x;
}

double project(double x, double lower, double upper) {
    if (x < lower) return lower;
    if (x > upper) return upper;
    return x;
}

void projected_gradient_descent(double x0, double alpha, int iterations, double lower, double upper) {
    double x = x0;
    for (int i = 0; i < iterations; i++) {
        x = project(x - alpha * df(x), lower, upper);
        printf("Iteration %d: x = %f, f(x) = %f\n", i, x, f(x));
    }
}

int main() {
    projected_gradient_descent(5.0, 0.1, 10, 0.0, 2.0);
    return 0;
}

まとめ

本記事では、C言語による数値的最適化の基本的な手法を解説しました。 勾配降下法、ニュートン法、準ニュートン法、制約付き最適化の実装を通して、それぞれの特性と適用範囲を理解することが重要です。

コメントは受け付けていません。