Подгонка кривой-монотонно возрастающая производная
Я пытаюсь получить физическое значимое соответствие некоторым экспериментальным данным. Я знаю, что не только значения y будут монотонно увеличиваться с x, но и что dy/dx также будет монотонно увеличиваться. Я попробовал несколько функций подгонки, включая полиномиальную подгонку и одномерный сплайн, но ни одна из них не позволила мне создать подгонку, которую я ищу.
Итак, я ищу функцию подгонки кривой (в scipy?) что позволит мне определить известные ограничения последняя кривая. Ниже приведен пример моих данных с подогнанной линией, которая не отображает монотонно возрастающую производную.
import numpy as np
import matplotlib.pyplot as plt
data = np.array([[ 6.30991828, -10.22329935],
[ 6.30991828, -10.2127338 ],
[ 6.47697236, -10.01359361],
[ 6.47697236, -9.89353722],
[ 6.47697236, -9.81708052],
[ 6.55108034, -9.42113403],
[ 6.55108034, -9.21932801],
[ 6.58617165, -8.40428977],
[ 6.62007321, -7.6500927 ]])
interp = np.linspace(min(data[:,0]), max(data[:,0]), 20)
f = np.polyfit(data[:,0], data[:,-1], 3)
data_interp = np.polyval(f, interp)
plt.plot(data[:,0], data[:,1], 'x', interp, data_interp, '-')
EDIT: я считаю, что вы можете сделать это в MATLAB с помощью slmengine.
2 ответа:
Правка: еще одна попытка. Я уже отправил наполовину испеченный ответ. И в чтении я тоже потерпел неудачу. Надеюсь, так будет лучше.
from scipy.optimize import minimize import numpy as np import matplotlib.pyplot as plt data = np.array([[ 6.30991828, -10.22329935], [ 6.30991828, -10.2127338 ], [ 6.47697236, -10.01359361], [ 6.47697236, -9.89353722], [ 6.47697236, -9.81708052], [ 6.55108034, -9.42113403], [ 6.55108034, -9.21932801], [ 6.58617165, -8.40428977], [ 6.62007321, -7.6500927 ]]) x = data[:, 0] def polynomial(p, x): return p[0]+p[1]*x+p[2]*x**2+p[3]*x**3 def constraint_2nd_der(p): return 2*p[2]+6*p[3]*x def constraint_1st_der(p): return p[1]+2*p[2]*x+3*p[3]*x**2 def objective(p): return ((polynomial(p, x)-data[:, 1])**2).sum() cons = (dict(type='ineq', fun=constraint_1st_der), dict(type='ineq', fun=constraint_2nd_der)) res = minimize(objective, x0=np.array([0., 0., 0., 0.]), method='SLSQP', constraints=cons) if res.success: pars = res.x x = np.linspace(data[:, 0].min(), data[:, 0].max(), 100) pol = polynomial(pars, x) plt.plot(data[:, 0], data[:, 1], 'x', x, pol, '-') plt.show() else: print 'Failed'
Ваши данные интересны: у вас есть три разрыва: в 6.30991828, 6.47697236 и 6.55108034. Они настоящие? Это то, что ты пытаешься поймать?
Ни одна непрерывная функция не может правильно уловить эти разрывы. Ваша единственная надежда-кусочно вписаться по обе стороны разрывов. У вас будет три припадка:
- x
- 6.47697236
- x > 6.55108034
Функция многозначна в точке разрывы, конечно.
Если они не имеют для вас значения, я бы сказал, что любой кубический полином даст вам непрерывную, возрастающую первую производную.