Хабрахабр

Вычисляем символьные выражения с нечеткими треугольными числами в python

Опишем класс нечетких треугольных чисел и операций над ними. В данном примере достаточно трех операций (сложение, вычитание и деление). Вводить операции будем с помощью перегрузки «магических» методов соответствующего класса:

class FuzzyTriangular(object): """Описание класса FuzzyTriangular""" def __init__(self, floatdigit = None, ABC = None, CAB = None, CDD = None): super(FuzzyTriangular, self).__init__() if ABC or floatdigit: if isinstance(floatdigit, (int, float)): self._a = Fraction(floatdigit) #левый "0" self._b = Fraction(floatdigit) #центр ("1") self._c = Fraction(floatdigit) #правый "0" elif isinstance(floatdigit, (tuple,list)): if len(floatdigit) == 2: #симметричное отклонение от центра self._a = Fraction(floatdigit[0] - abs(floatdigit[1])) #левый "0" self._b = Fraction(floatdigit[0]) #центр ("1") self._c = Fraction(floatdigit[0] + abs(floatdigit[1])) #правый "0" else: #3 и более, воспринимаются первые 3 self._a = Fraction(floatdigit[0]) #левый "0" self._b = Fraction(floatdigit[1]) #центр ("1") self._c = Fraction(floatdigit[2]) #правый "0" else: self._a = Fraction(ABC[0]) #левый "0" self._b = Fraction(ABC[1]) #центр ("1") self._c = Fraction(ABC[2]) #правый "0" self._center = self._b #центр self._alpha = self._b - self._a #отклонение от центра влево self._beta = self._c - self._b #отклонение от центра вправо self._d = (self._alpha + self._beta)/2 self._delta = (self._beta - self._alpha)/2 elif CAB: self._center = Fraction(CAB[0]) #центр self._alpha = Fraction(CAB[1]) #отклонение от центра влево self._beta = Fraction(CAB[2]) #отклонение от центра вправо self._d = (self._alpha + self._beta)/2 self._delta = (self._beta - self._alpha)/2 self._b = self._center #центр ("1") self._a = self._center - self._alpha #левый "0" self._c = self._center + self._beta #правый "0" elif CDD: self._center = Fraction(CDD[0]) #центр self._d = Fraction(CDD[1]) self._delta = Fraction(CDD[2]) self._alpha = self._d - self._delta #отклонение от центра влево self._beta = self._d + self._delta #отклонение от центра вправо self._b = self._center #центр ("1") self._a = self._center - self._alpha #левый "0" self._c = self._center + self._beta #правый "0" else: raise Exception("No input data to create class") def __repr__(self): return str((round(float(self._a), 12), round(float(self._b), 12),\ round(float(self._c), 12))) def __CDD_add(self, other): center = self._center + other._center d = self._d + other._d delta = self._delta + other._delta return FuzzyTriangular(CDD = (center, d, delta)) def __CDD_sub(self, other): center = self._center - other._center d = self._d + other._d delta = self._delta - other._delta return FuzzyTriangular(CDD = (center, d, delta)) def __CDD_mul(self, other): center = self._center*other._center d = abs(self._center)*other._d + abs(other._center)*self._d delta = self._center*other._delta + other._center*self._delta return FuzzyTriangular(CDD = (center, d, delta)) def __add__(self, other): if isinstance(other, FuzzyTriangular): return self.__CDD_add(other) else: return self.__CDD_add(FuzzyTriangular(other)) def __sub__(self, other): if isinstance(other, FuzzyTriangular): return self.__CDD_sub(other) else: return self.__CDD_sub(FuzzyTriangular(other)) def __mul__(self,other): if isinstance(other, FuzzyTriangular): return self.__CDD_mul(other) else: return self.__CDD_mul(FuzzyTriangular(other)) def __pos__(self): return FuzzyTriangular(1)*self def __neg__(self): return FuzzyTriangular(-1)*self def __eq__(self, other): return (self._a == other._a) and (self._b == other._b) and \ (self._c == other._c)

Формы представления нечетких треугольных чисел могут быть разные, не будем углубляться. В представленном коде обратим внимание на методы __add__ (оператор сложения), __sub__ (оператор вычитания), __mul__ (оператор умножения). Если попытаться к нечеткому треугольному числу прибавить вещественное число, то оно будет преобразовано в нечеткое треугольное. Аналогичная ситуация с кортежем или списком из вещественных чисел — первые три числа будут восприниматься как нечеткое треугольное (и также преобразовываться в класс FuzzyTriangular). Метод __pos__ переопределяет унарный оператор "+". Метод __neg__ — унарный "-". Метод __eq__ переопределяет оператор "==". При желании можно дополнительно переопределить такие операции как:

  • деление
  • возведение в степень
  • модуль числа
  • сравнения (больше/меньше, больше либо равно/меньше либо равно)
  • скаляризация (приведение к int, float, complex числам, округление)
  • инверсия и др...

Проверить адекватность введенных операций можно небольшим набором тестов, например таких:

ZERO = FuzzyTriangular((0,0,0))
ONE = FuzzyTriangular((1,1,1))
A = FuzzyTriangular((0.3,0.5,0.9))
B = FuzzyTriangular((0.2,0.4,0.67))
C = FuzzyTriangular((0,0.33,0.72)) print('ZERO = '+str(ZERO))
print('ONE = '+str(ONE))
print('A = '+str(A))
print('B = '+str(B))
print('C = '+str(C)) #some tests
print('\nСЛОЖЕНИЕ')
print('A + B = ', A + B)
print('A + B == B + A', A + B == B + A) #введение оператора сравнения
print('A + C = ', A + C)
print('A + C == C + A', A + C == C + A)
print('B + C = ', B + C)
print('B + C == C + B', B + C == C + B)
print('A + B + C = ', A + B + C)
print('(A + B) + C == A + (B + C) == (A + C) + B', \ (A + B) + C == A + (B + C) == (A + C) + B)
print('C + 1 = ', C + 1)
print('1 + C = ', ONE + C) print('\nВЫЧИТАНИЕ')
print('A - A =', A - A)
print('A - A == 0', A - A == ZERO)
print('A - B = ', A - B)
print('B - A = ', B - A)
#введение унарных операторов "-" и "+"
print('A - B == -(B - A)', A - B == -(B - A))
print('(A + B + C) - (A + B) = ', (A + B + C) - (A + B))
#необходимость использования рациональных дробей
print('(A + B + C) - (A + B) == C', (A + B + C) - (A + B) == C)
print('1 - A = ', ONE - A)
print('A - 1 = ', A - 1)
print('1 - A == -(A - 1)', ONE - A == -(A - 1)) print('\nУМНОЖЕНИЕ')
print('A*B == B*A', A*B == B*A)
print('-1*C =', -ONE*C)
print('-1*C == -C', -ONE*C == -C)
print('-1*C == C*-1', -ONE*C == C*-1)
print('C*-1 = ', C*-1)
print('C*-1 =', C*-1)
print('-C*1 == -C', -C*1 == -C)
print('-C*1 =', -C*1)
print('-C =', -C)
print('C*-1 == -C', C*-1 == -C)
print('(A + B)*C == A*C + B*C', (A + B)*C == A*C + B*C)
print('(A - B)*C == A*C - B*C', (A - B)*C == A*C - B*C)
print('A*C = ', A*C)
print('B*C = ', B*C)
print('-B*C = ', -B*C)
print('-B*C == B*-C', -B*C == B*-C)
print('B*C == -B*-C', B*C == -B*-C)

Эти проверочные операции сложения, деления и умножения задаются в коде и выполняются согласно переопределению «магических» методов. Нам бы хотелось иметь возможность осуществлять такие же операции с использованием символьных переменных в заранее неизвестных выражениях. Для этого требуется ввести несколько вспомогательных функций.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть