powered by simpleCommunicator - 2.0.48     © 2025 Programmizd 02
Форумы / Публикации участников форума [игнор отключен] [закрыт для гостей] / Как нарушить принцип подстановки Лисков не привлекая внимания санитаров+
3 сообщений из 3, страница 1 из 1
Как нарушить принцип подстановки Лисков не привлекая внимания санитаров+
    #40141012
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
или 'арифметические вычисления и небезопасность универсального полифорфизма'

проект
arithmetic -- классы для для симплекс метода
побочный эффект - разный результат в вычислениях (3 * 5) / 2
из-за разного округления в классе целых.

Очередной пример нарушения принципа, который сводит к нулю
пользу от универсального полиморфизма в обеих формах.
Как от полиморфизма включения, так и от полиморфизма шаблонов.

Есть две версии полиморфной функции:
одна написана в терминах базового класса (каталог v2/PrgFunc.cs)
Код: C#
1.
2.
3.
4.
    static int function ( number one,  number two, number toChangeVal) {
       number out1 = (one * two ) /  toChangeVal;
       return (int) out1;
    }
вторая, как шаблон (каталог v3/PrgFunc.cs):
Код: C#
1.
2.
3.
4.
5.
    static int
    function<T> ( T one,  T two, T toChangeVal) where T : number  {
       number out1 = (one * two ) / toChangeVal;
       return (int) out1;
    }
Округление до целого в них выполняется при помощи обычного отбрасывания дробной части:
(int) out1;

Но в классе целых деление переопределено так, что используется банковское округление
и 15 : 2 дает 8

в результате обе версии полиморфной функции возвращают
разные значения то ли 7, то ли 8 в зависимости от реального класса объектов.

Это результат (надеюсь) всем известных проблем с условиями
контра- и ко- вариантностью
функционального типа метода. Эти условия всем разжевали Б.Мейер и Л.Карделли.
для методов (функций) у которых множество объектов класса появляется
с левой и с правой стороны функциональнй стрелки:

f: domen(class) >< X -> domen(class) >< Y
(для любых множеств X и Y)
/*
Стало понятно после формального анализа примера Мартина
с наследованием квадратов и прямоугольников
в статье Об отличиях между понятиями типа и класса
https://www.researchgate.net/publication/344177979
, что условия в родительском классе можно задавать таким образом, что область определения
и множество значений метода не будет меняться. Но к нарушению принципа подстановки будет приводить.
*/

В такую группу методов попадают все алгебраические операции:
domen(class) >< domen(class) -> domen(class)
То есть, функции для вычисления чего либо, скорее всего, нельзя писать
полиморфные.
/*
в Переопределении сложения: небезопасное наследование
в группе целых
(https://www.researchgate.net/publication/366867037)
приводился пример с проблемой на операциях вычитания, переход от полугруппы натуральных к группе целых)

*/

В частности, в этом примере, проблема заключается в операциях деления (переход от кольца целых к полю вещественных)
Код: C#
1.
2.
3.
4.
  // class integer
  public  override  number div( number r){
          return new integer (round( v / round(r.v)));
        }
И
Код: C#
1.
2.
3.
4.
 // class real
    public  override  number div( number r){
          return new integer (v / r.v));
        }
Мейер и Карделли показывали пальцем на эксепшены полиморфной функции.
в текущем примере полиморфные функции (function) не выбрасывает эксепшен,
а тихонько начинает нарушать начальное требования
-- для округления использовать отбрасывание
дробной части. Это еще хуже, чем эксепшн.

Классы integer и real были отлажены, что бы показать как плохо
станет работать полиморфный симплекс метод.
В текущем примере результат сем-восем еще такое дело,
а неправильная оптимизация в симплекс методе явно будет нарушать
начальную спецификацию при попытке использовать универсальный полиморфизм.

Виды округления в Си Шапре согласно IEEE 754 -2019
Округление к ближайшему или четному (Банковское округление)
Math.Round(v, MidpointRounding.ToEven)
Округление к ближайшему или большему по модулю
Math.Round(v, MidpointRounding.AwayFromZero)

выбирается ближайшее целое число, а если их два - то,
в первом случае -- четное, во втором -- большее по модулю.

Округление отбрасыванием дробной части
(int) v или Math.Truncate(v)

Округление к положительной бесконечности
из двух целых чисел выбирается большее:
Math.Ceiling(v) или
Math.Round(value, MidpointRounding.ToPositivetiveInfinity)
Округление к отрицательной бесконечности
из двух целых чисел выбирается меньшее:
Math.Floor(v ) или Math.Round(value, MidpointRounding.ToNegativetiveInfinity)
arithmetic_02.00.01.zip
...
Изменено: 26.06.2025, 19:24 - tchingiz
Рейтинг: 0 / 0
Как нарушить принцип подстановки Лисков не привлекая внимания санитаров+
    #40141118
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
В кольце целых не выполняется требование о наличии обратного элемента для каждого числа по делению.
В отличие от поля, кольцо по делению полугруппа.
Ссылка на раздел 6.1 Степанов А.А. От математики к обобщенному программированию.
Текст из Степанова переписан на языке RAISE specification language
scheme group = class type T value e : T -- identity element ,op : T >< T -> T -- group operation ,inverse : T -> T -- inverse operation axiom [associativity] all x,y,z : T :- op (x, op(y,z)) is op (op(x,y), z) ,[identity] all x : T :- (op (x, e) is x ) /\ (op (e, x) is x) ,[cancellation] all x : T :- op (x, inverse(x)) is e end
В качестве тренировки.
На практике условия из аксиом надо использовать для кодирования тестовых вариантов,
как это делалось на примере аксиом метрического пространства
https://resql.ru/forum/topic.php?fid=71&tid=2187231
...
Рейтинг: 0 / 0
Как нарушить принцип подстановки Лисков не привлекая внимания санитаров+
    #40141139
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Получилось хорошо. Как и ожидалось, обобщенная версия симплекс метода плохо находит максимум при целых числах.
То есть, нарушает принцип подстановки.

Не обобщенная версия на double лежит тут https://resql.ru/forum/topic.php?fid=71&tid=2187253.

Надо вручную пересчитать.

Пришлось использовать фабрику, вместо конструкторов с параметром вещественное число.
Код: C#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
 public interface ICreatable { void set (double s); }

partial class real: ICreatable {
  public real (): this(0.0) { }
  public real (real v)    { this.v = v.v;}
  public real (double v)    { this.v = v;}
  public real (string s)    {
     if (!double.TryParse (s, out v))
        this.v = 0.0;
   }
  public static implicit operator real (double d) { return new real(d);}
  public static implicit operator string(real v)  { return v.v.ToString(); }
  public static implicit operator double(real v)  { return v.v; }

  public virtual void set( double r){  v = r;}   ////// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}

  partial class simplex<T> where T : real,     new() {
    public static string name (  ) {
      return  string.Format(" '{0}' type", typeof(T));
    }

    public static T make(double s) {///  вместо конструктора с вещественным параметром
        T obj = new T();
        obj.set(s);                           ///<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        return obj;
    }
Округление банковское использовано.
simplexM_2.00.00.zip
...
Изменено: Вчера, 16:51 - tchingiz
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Публикации участников форума [игнор отключен] [закрыт для гостей] / Как нарушить принцип подстановки Лисков не привлекая внимания санитаров+
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]