# C++에서 미분 (Differentiation in C++)

#### 개요

C++에서 미분을 구현하는 것은 수치 해석(numerical analysis)과 자동 미분(automatic differentiation) 기법을 통해 이루어진다. 이 과정은 함수의 도함수를 계산하고, 이를 다양한 수치 문제에 적용하기 위해 사용된다. 미분을 직접적으로 구현하는 것은 이산적(discrete) 환경에서 이루어지며, 미분의 수치적 근사치와 정확한 자동 미분 방법이 주로 사용된다. C++에서는 이러한 작업을 수행하기 위해 다양한 라이브러리와 알고리즘이 활용된다.

#### 수치 미분 (Numerical Differentiation)

수치 미분은 함수를 분석적으로 미분할 수 없거나 복잡할 때, 이를 근사적으로 계산하는 방법이다. 가장 일반적인 방법은 전방 차분(forward difference)와 중심 차분(central difference)이다. 이 방법들은 미분의 정의를 활용하여 함수의 도함수를 근사한다.

**전방 차분 (Forward Difference)**

전방 차분은 다음과 같은 형태로 표현된다:

$$
f'(x) \approx \frac{f(x+h) - f(x)}{h}
$$

여기서 $ h $는 매우 작은 값이며, 이는 도함수의 근사치를 제공한다. 이 방법은 구현이 간단하지만, $ h $의 선택에 따라 오차가 발생할 수 있다.

```cpp
double forward_difference(double (*f)(double), double x, double h) {
    return (f(x + h) - f(x)) / h;
}
```

**중심 차분 (Central Difference)**

중심 차분은 전방 차분보다 더 정밀한 방법으로, 다음과 같이 정의된다:

$$
f'(x) \approx \frac{f(x+h) - f(x-h)}{2h}
$$

이 방법은 $ h $가 작을수록 더 정확한 결과를 제공하며, 전방 차분보다 오차가 줄어드는 경향이 있다.

```cpp
double central_difference(double (*f)(double), double x, double h) {
    return (f(x + h) - f(x - h)) / (2 * h);
}
```

#### 자동 미분 (Automatic Differentiation)

자동 미분은 컴퓨터에서 함수를 미분하는 가장 정확한 방법 중 하나로, 코드에서 수치적 오류를 최소화하고 정확한 도함수를 계산할 수 있다. 자동 미분은 기호 미분(symbolic differentiation)과 수치 미분의 중간 지점에 있으며, 프로그램이 실행되는 동안 계산 그래프를 따라 미분을 수행한다.

**전방 모드 (Forward Mode)**

전방 모드 자동 미분은 기본적으로 체인 룰(chain rule)을 적용하여 미분을 계산한다. 이 방법은 함수의 각 입력값에 대해 하나씩 도함수를 계산하는 방식으로 작동한다.

```cpp
struct Dual {
    double value;
    double derivative;

    Dual(double v, double d) : value(v), derivative(d) {}

    Dual operator+(const Dual& other) const {
        return Dual(value + other.value, derivative + other.derivative);
    }

    Dual operator*(const Dual& other) const {
        return Dual(value * other.value, value * other.derivative + derivative * other.value);
    }
};

Dual f(const Dual& x) {
    return x * x + x + 1.0;
}
```

이 코드 예시에서, `Dual` 구조체는 함수의 값과 도함수를 동시에 저장하며, 이를 통해 전방 모드 자동 미분을 수행할 수 있다.

**역방향 모드 (Reverse Mode)**

역방향 모드 자동 미분은 특히 다변수 함수의 미분에 효율적이다. 이는 출력에서부터 입력으로 역전파(backpropagation)하면서 도함수를 계산한다. 이 방법은 기계 학습에서의 경사 하강법(gradient descent) 등에서 중요한 역할을 한다.

```cpp
struct Node {
    double value;
    double adjoint;

    Node(double v) : value(v), adjoint(0) {}
};

struct ComputationalGraph {
    std::vector<Node*> nodes;

    void add(Node* node) {
        nodes.push_back(node);
    }

    void backpropagate() {
        for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) {
            (*it)->adjoint = 1.0; // 역전파 기초
            // 추가적인 코드로 adjoint를 전파
        }
    }
};
```

이 구조에서, 각 노드는 그래프에서의 계산 노드를 나타내며, 역전파를 통해 도함수를 계산한다.

#### C++ 라이브러리

C++에서 자동 미분을 구현하는 데는 다양한 라이브러리가 존재한다. 대표적으로 Eigen, CppAD, Adept 등이 있으며, 이들은 각각 전방 모드와 역방향 모드를 지원하는 다양한 기능을 제공한다. 이러한 라이브러리들은 높은 성능과 함께 편리한 API를 제공하여 복잡한 함수의 미분을 간단히 구현할 수 있다.
