Skip to content

Instantly share code, notes, and snippets.

@wakita
Created November 12, 2019 00:21
Show Gist options
  • Save wakita/0619162e8c1f3a69f947490276c647ab to your computer and use it in GitHub Desktop.
Save wakita/0619162e8c1f3a69f947490276c647ab to your computer and use it in GitHub Desktop.
{(x_i, f(x_i)} が等間隔に並ぶような点列 {x_i} を求める
import numpy as np
from crfmnes import CRFMNES
np.set_printoptions(formatter={'float_kind': lambda f: f"{f:.2f}"})
def divide(f, x0, xn, n):
'''
divide: p_i = (x_i, f(x_i)) (i = 0, 1, ..., n) について、
x_0 = x0, x_n = xn, (x_{i-1}, f_{x_{i-1}}) = (x_i, f_{x_i})
となる分割を求める。
[x0, xn]: 区間
n: 区間の区分数
'''
xs = (xn - x0) * np.arange(0, n+1) / n + x0
xs = xs[1:-1]
def sq_distance(x0, x1):
return np.square(x1 - x0) + np.square(f(x1) - f(x0))
def dists(xs):
xs = xs.reshape(-1, 1)
d = np.empty((n,1))
d[0] = sq_distance(xs[0, 0], x0)
d[1:-1] = sq_distance(xs[1:], xs[:-1])
d[-1] = sq_distance(xn, xs[-1, 0])
return np.sqrt(d)
def objective(xs):
return np.var(dists(xs))
print('xs:', xs)
print('distances:', dists(xs).reshape(-1,))
print()
optimizer = CRFMNES(np.size(xs), objective, xs.reshape(-1, 1), 1, 16)
xs, f_best = optimizer.optimize(1000)
xs = xs.reshape(-1,)
print('xs:', xs)
print('distances:', dists(xs).reshape(-1,))
print('f(x) = x*x')
divide(lambda x: x * x, -3, 3, 10)
print('f(x) = x*x*x')
divide(lambda x: x * x * x, -3, 3, 10)
@wakita
Copy link
Author

wakita commented Nov 12, 2019

x^2, x^3 についての実行結果です。

f(x) = x*x
xs: [-2.40 -1.80 -1.20 -0.60 0.00 0.60 1.20 1.80 2.40]
distances: [3.30 2.59 1.90 1.24 0.70 0.70 1.24 1.90 2.59 3.30]

xs: [-2.57 -2.07 -1.40 0.00 1.40 0.00 1.40 2.07 2.57]
distances: [2.41 2.41 2.41 2.41 2.41 2.41 2.41 2.41 2.41 2.41]
f(x) = x*x*x
xs: [-2.40 -1.80 -1.20 -0.60 0.00 0.60 1.20 1.80 2.40]
distances: [13.19 8.01 4.15 1.63 0.64 0.64 1.63 4.15 8.01 13.19]

xs: [-2.62 -2.07 -2.62 -2.07 -2.62 -2.07 0.00 2.07 2.62]
distances: [9.09 9.09 9.09 9.09 9.09 9.09 9.09 9.09 9.09 9.09]

@wakita
Copy link
Author

wakita commented Nov 12, 2019

考察

  • 目的関数を np.var(dists(xs)) とするより np.sum(dists(xs)) とする方が素直だと思ったのだけど関数の性質によってはおかしなことに

    • 1点がx0となり、残りがすべてxnになる
      になるのが残念。区間 R について max f(R) > |R| なときにこの問題が発生する。
  • もともとは dists はユークリッド距離ではなく、その二乗を返していた。それでも大丈夫かと思っていたのだけど、結果は滅茶苦茶だった。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment