Квадратичное к цепочке или соединению нескольких кусочков в Python

Я некоторое время копался в stackoverflow и не могу найти ни одного примера для нескольких кусочных кривых. Я хочу преобразовать квадратичную функцию в множественную цепочку (я не знаю ее точного названия, но мне нужно, чтобы каждый хвост был соединен с головой следующего кусочно, просто «связан») кусочной функции. Это мой код, использующий scipy.optimize для преобразования квадратичной функции в две части кусочно-линейной функции.

    import scipy.optimize as opt
    import numpy as np
    import copy

    def func_2piecewise(x, m_0, x_1, y_1, m_1):
        y = np.piecewise(x, [x <= x_1, x > x_1],
                            [lambda x:m_0*(x-x_1) + y_1, lambda x:m_1*(x-x_1) + y_1])
        return y

    xmin=0
    xmax=100
    a=0.1
    a0=1
    a00=10
    piece_number=2
    sigma=np.ones(numberOfStep)
    if piece_number==2:
        lower_bounds=[-np.inf,xmin,-np.inf,-np.inf]
        upper_bounds=[np.inf,xmax,np.inf,np.inf]

        w, _ = opt.curve_fit(func_2piecewise, x_sample, y_sample,bounds=(lower_bounds,upper_bounds),sigma=sigma)
        x_0=copy.deepcopy(xmin)
        y_0=func_2piecewise(x_0, *w).tolist()
        [m_0, x_1, y_1, m_1]=w
        result=[x_0,y_0,m_0,x_1,y_1,m_1]

Проблема в том, что я не могу реализовать один и тот же подход для трех кусков (я не знаю, как сделать x_2 > x_1):

    def func_gradients(x_list,y_list):
        len_x_list=len(x_list)
        if len_x_list==1:
            m_list=y_list/x_list
            return m_list
        m_list=[]
        for idx in range(len_x_list-1):
            m_list.append((y_list[idx+1]-y_list[idx])/(x_list[idx+1]-x_list[idx]))
        return m_list
    def func_3piecewise(x, m_0, x_1, y_1, x_2, y_2, m_2):
        y = np.piecewise(x, [x <= x_1, (x > x_1) & (x <= x_2), x > x_2],
                        [lambda x:m_0*(x-x_1) + y_1, lambda x:y_1+(y_2-y_1)*(x-x_1)/(x_2-x_1), lambda x:m_2*(x-x_2) + y_2])
        return y
    if piece_number==3:
        lower_bounds=[-np.inf,xmin,-np.inf,xmin,-np.inf,-np.inf]
        upper_bounds=[np.inf,xmax,np.inf,xmax,np.inf,np.inf]

        w, _ = opt.curve_fit(func_3piecewise, x_sample, y_sample,bounds=(lower_bounds,upper_bounds),sigma=sigma)
        x_0=copy.deepcopy(xmin)
        y_0=func_3piecewise(x_0, *w).tolist()
        [m_0, x_1, y_1, x_2, y_2, m_2]=w
        m_1=func_gradients(x_2-x_1,y_2-y_1)
        result=[x_0,y_0,m_0,x_1,y_1,m_1, x_2, y_2, m_2]

Полный код можно увидеть в pastebin.

Итак, вопрос: Как сделать цепочку (каждый хвост кусочной функции, связанный с головой следующей части или просто «связанной») кусочной функцией в python для общих n частей? Допускается другой алгоритм или решатель.

Изменить: я добавляю свой результат до сих пор для 2 штук.

Обновление: я обнаружил, что мой код (из трех частей) не работает из-за небольшой опечатки (извините за это, просто скажите, следует ли мне удалить этот вопрос). Теперь это работает, и я обновляю корзину для пасты. Но, если у вас есть общая (гибкая, не нужно писать функцию для каждого варианта числа) функция, которая может генерировать n штук, я с радостью приму ответ.

Результат на 2 штуки поштучно


person Py Foliage    schedule 28.03.2020    source источник
comment
Вы говорите, что я не могу реализовать такой же подход и сразу показываете вашу реализацию. В чем проблема? Ваша реализация не работает? Как-то плохо работает? Вы можете отредактировать свой вопрос, чтобы внести ясность.   -  person anatolyg    schedule 28.03.2020
comment
Что означает цепочка? Вы говорите, что продолжается в x, но не продолжает функцию, но я этого не понимаю. Прояснить?   -  person anatolyg    schedule 28.03.2020
comment
@anatolyg Я даю объяснение по этому поводу. То, что я имею в виду под цепочкой, похоже на цепочку, где каждый хвост кусочно соединен с головой следующего кусочно.   -  person Py Foliage    schedule 28.03.2020


Ответы (1)


Вы можете параметризовать расстояние x2-x1 вместо параметризации x2. Поскольку вы можете указать границы оптимизатора, вы можете установить расстояние больше 0.

Например, чтобы сделать общую кусочно-линейную функцию с 4 интервалами, определите следующее:

Точки, которые разделяют интервалы и x0, x1 и x2. Уклоны в 4 интервалах составляют m0, m1, m2 и m3. Значение функции в точке x0 равно y0.

Определить d1 = x1 - x0, d2 = x2 - x1. Отсюда:

x1 = x0 + d1
x2 = x0 + d1 + d2

Затем у вас есть 8 параметров оптимизации: x0, y0, d1, d2, m0, m1, m2 и m3. По характеру вашей задачи оптимизации все, кроме x0 и y0, неотрицательны.

Уравнение для первого интервала:

y = m0 * (x - x0) + y0

Уравнение для второго интервала:

y = m1 * (x - x0) + y0

Теперь вы можете получить остальные уравнения рекурсивным способом, применяя предыдущее уравнение в самой правой точке его интервала. Для точки x1 значение функции равно:

y1 = m1 * d1 + y0

Итак, третье уравнение

y =
    m2 * (x - x1) + y1 =
    m2 * (x - x0 - d1) + m1 * d1 + y0

Для точки x2 это дает

y2 = m2 * d2 + y1

Итак, четвертое уравнение

y =
    m3 * (x - x2) + y2 =
    m3 * (x - x0 - d1 - d2) + m2 * d2 + m1 * d1 + y0
person anatolyg    schedule 28.03.2020
comment
Я попробую это закодировать. И сообщить о результате. Спасибо. - person Py Foliage; 29.03.2020
comment
Я обнаружил, что проблема при реализации вашего (это небольшая опечатка в моем коде). Я обновил свой вопрос и пока отмечу ваш ответ как принятый ответ. Спасибо!!! - person Py Foliage; 29.03.2020