2016年9月7日水曜日

開発環境

Pythonからはじめる数学入門 (Amit Saha (著)、黒川 利明 (翻訳)、オライリージャパン)の7章(初等解析問題を解く)、7.10(プログラミングチャレンジ)、問題7-2(勾配降下法を実装する)を取り組んでみる。

問題7-2(勾配降下法を実装する)

コード(Emacs)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sympy
import matplotlib.pyplot as plt


def grad_descent(x0, f1x, x):
    if not sympy.solve(f1x):
        print('Cannot continue, solution for {0}=0 does not exist'.format(f1x))
        return
    epsilon = 1e-6
    step_size = 1e-4
    x_old = x0
    x_new = x_old - step_size * f1x.subs({x: x_old}).evalf()
    xs = []
    while abs(x_old - x_new) > epsilon:
        xs.append(x_new)
        x_old = x_new
        x_new = x_old - step_size * f1x.subs({x: x_old}).evalf()

    return x_new, xs


def frange(start, stop, step):
    numbers = [start]
    while start < stop:
        start += step
        numbers.append(start)
    return numbers


def draw(x, f, var, xs):
    x0 = -abs(x) * 1.5
    x1 = -x0
    xs0 = frange(x0, x1, (x1 - x0) / 100)
    ys0 = [f.subs({var: x}) for x in xs0]
    plt.plot(xs0, ys0)
    ys = [f.subs({var: x}) for x in xs]
    plt.plot(xs, ys, marker='o')

if __name__ == '__main__':
    f = input('Enter a function in one variable: ')
    var = input('Enter the variable to differentiate with respect to: ')
    var0 = float(input('Enter the initital value of variable: '))
    try:
        f = sympy.sympify(f)
    except sympify.SympifyError as err:
        print(err)
    else:
        var = sympy.Symbol(var)
        d = sympy.Derivative(f, var).doit()
        var_min, xs = grad_descent(var0, d, var)
        if var_min:
            plt.figure(figsize=(5, 5))
            print('{0}: {1}'.format(var.name, var_min))
            print('Minimum value: {0}'.format(f.subs({var: var_min})))
            draw(var0, f, var, xs)
            plt.savefig('sample2.png')

入出力結果(Terminal, IPython)

$ ./sample2.py
Enter a function in one variable: 1/2*x**2 + 1
Enter the variable to differentiate with respect to: x
Enter the initital value of variable: 1.001
x: 0.00999839378867327
Minimum value: 1.00004998393918
$

0 コメント:

コメントを投稿