Исходный код miptlabs.approximators.special

import numpy as np
import scipy.fftpack
import scipy.optimize

from . import functions
from .base import Polynomial, Functional, Approximator, MultiLinearMixin
from ..utils import round_to_n, format_monoid


[документация]class Linear(Polynomial): """ Аппроксимация с помощью прямой y=kx+b. Использует numpy.polyfit """ def __init__(self, points=100, left_offset=5, right_offset=5, no_bias=False): """ :param points: количество точек, которые будут на выходе :param left_offset: отступ от правой границы диапазона :param right_offset: отступ, то свободного коэффициента нет, иначе есть :param no_bias: Если *True* от левой границы диапазона """ super(Linear, self).__init__(1, points, left_offset, right_offset) self.no_bias = no_bias # Данные self.__k = None self.__b = None
[документация] def approximate(self, x, y, xerr=0, yerr=0): x, y, xerr, yerr = self._prepare_before_approximation(x, y, xerr, yerr) if not self.no_bias: return super(Linear, self).approximate(x, y, xerr, yerr) else: # fixme: убрать дублирование кода popt, pcov = scipy.optimize.curve_fit( f=functions.line_for_fit, xdata=x, ydata=y, sigma=yerr) perr = np.sqrt(np.diag(pcov)) self.meta = { 'popt': popt, 'pcov': pcov } self.koefs = popt self.sigmas = perr self._function = functions.line(popt[0]) xs = self._gen_x_axis_with_offset(min(x), max(x)) ys = self._function(xs) return xs, ys
[документация] def label(self, xvar='x', yvar='y'): res = f'{format_monoid(self.koefs[0])}{xvar}' if not self.no_bias: res += format_monoid(self.koefs[1]) # убираем плюс при максимальной степени # FIXME неоптимизированный костыль с копирование строк if self.koefs[0] >= 0: res = res[1:] return f"${yvar} = {res}$"
def _brac_x(self): return self._x.mean() def _brac_y(self): return self._y.mean() def _brac_x2(self): return (self._x * self._x).mean() def _brac_y2(self): return (self._y * self._y).mean() def _brac_xy(self): return (self._x * self._y).mean() def _d_xy(self): return (self._x - self._x.mean()).mean() * (self._y - self._y.mean()).mean() def _d_xx(self): return np.square(self._x - self._x.mean()).mean() def _d_yy(self): return np.square(self._y - self._y.mean()).mean() def _k(self): self.__k = (self._brac_xy() - self._brac_x() * self._brac_y()) / (self._brac_x2() - self._brac_x() ** 2) return self.__k def _b(self): if self.__k is None: self._k() self.__b = self._brac_y() - self.__k * self._brac_x() return self.__b def _sigma_k(self): if self.__k is None: self._k() if len(self._x) == 2: return 0 return np.sqrt(np.abs((self._d_yy() / self._d_xx() - self._k() ** 2) / (len(self._x) - 2))) def _sigma_b(self): if self.__b is None: self._b() return self._sigma_k() * np.sqrt(self._brac_x2())
[документация]class Exponential(Functional): """ Экспоненциальный апроксиматор y = a*exp(bx)+c """ def __init__(self, points=100, left_offset=5, right_offset=5): """ :param points: количество точек, которые будут на выходе :param left_offset: отступ от правой границы диапазона :param right_offset: отступ, то свободного коэффициента нет, иначе есть """ super(Exponential, self).__init__( function=functions.exp_for_fit, points=points, left_offset=left_offset, right_offset=right_offset )
[документация] def label(self, xvar='x', yvar='y'): try: return f'${yvar} = {format_monoid(round_to_n(self.koefs[0], 3), True)}' \ f'e^{{{round_to_n(self.koefs[1], 3)}{xvar}}} ' \ f'{format_monoid(round_to_n(self.koefs[2], 3))}$' except TypeError: return 'Экспонента, которая не смогла'
[документация]class Logarithmic(Functional): """ Логарифмический апроксиматор y = a * ln(bx + c) + d """ def __init__(self, points=100, left_offset=5, right_offset=5): """ :param points: количество точек, которые будут на выходе :param left_offset: отступ от правой границы диапазона :param right_offset: отступ, то свободного коэффициента нет, иначе есть """ super(Logarithmic, self).__init__( function=functions.log_for_fit, points=points, left_offset=left_offset, right_offset=right_offset )
[документация] def label(self, xvar='x', yvar='y'): try: return f'${format_monoid(round_to_n(self.koefs[0], 3), True)}\ln{{(' \ f'{format_monoid(round_to_n(self.koefs[1], 3), True)}x ' \ f'{format_monoid(round_to_n(self.koefs[2], 3))})}} ' \ f'{format_monoid(round_to_n(self.koefs[3], 3))}$' except IndexError: return 'Логарифм, который не смог'
class TANH(Functional): """ Логарифмический апроксиматор y = a * ln(bx + c) + d """ def __init__(self, points=100, left_offset=5, right_offset=5): """ :param points: количество точек, которые будут на выходе :param left_offset: отступ от правой границы диапазона :param right_offset: отступ, то свободного коэффициента нет, иначе есть """ super(TANH, self).__init__( function=functions.log_for_fit, points=points, left_offset=left_offset, right_offset=right_offset ) def label(self, xvar='x', yvar='y'): try: return f'${format_monoid(round_to_n(self.koefs[0], 3), True)}\ln{{(' \ f'{format_monoid(round_to_n(self.koefs[1], 3), True)}x ' \ f'{format_monoid(round_to_n(self.koefs[2], 3))})}} ' \ f'{format_monoid(round_to_n(self.koefs[3], 3))}$' except IndexError: return 'Логарифм, который не смог' class StupidApproximator(MultiLinearMixin, Approximator): """ Аппроксиматор, который просто соединяет соседние точки прямой """