Search
Write a publication
Pull to refresh
43
0
Валерий Дмитриев @rotor

Пользователь

Send message

Я как раз хотел предложить метрику на основе взаимной информации, но вы меня опередили :) сейчас ниже напишу что я придумал.

То что вы предлагаете описано в п 2.2. но там используется Precision и Recall, а вы предлагаете использовать Accuracy.
Практика показывает, что не смотря на кажущуюся интуитивность этой метрики, она плохо работает в случае дисбаланса классов.
Поэтому в ML не принято использовать Accuracy.

Часто пишу на D и C++ и как C++ разработчик вижу проблему D в неправильном позиционировании.
Слоган D: "write fast, read fast, run fast" и это в целом правда. На D действительно можно быстро писать читаемый код, который при этом будет относительно быстро исполняться. Есть режим "интерпретатора" для быстрой отладки и прототипирования.
Язык очень удобен, но ни как замена C++, а как замена Python!
Современный С++ самодостаточен и хорош для тех кто его знает. Пытаясь стать заменой C++ D плывёт против течения.
Высокая производительность C++ обусловлена:


  1. Возможностью полностью контролировать поток выполнения как на высоком так и на низком уровне
  2. Возможностью фронтенда компилятора выполнять оптимизации, недоступные в более безопасных языках. Все эти вещи, которые помечены в стандарте как UB дают компилятору возможность для оптимизаций.
    У D тоже получается собрать весьма эффективный код с ldc2, но оптимизаций бэкенда недостаточно. И он никогда не будет столь же быстр как C++. Даже без учёта GC.

А вот использовать D там, где используют, например Python, действительно круто.
У D достаточно много библиотек (хотя многие и весьма сырые). У D прогрессивная сложность. На нём легко начать писать с минимальной подготовкой. Код получается компактный и читаемый. Потрясающая шаблонная магия позволяет делать красивые библиотеки, которыми легко пользоваться. Встроенные юниттесты. Типобезопасность. Бинарь без зависимостей на выходе. И много много чего ещё.


D например, мог бы стать потрясающим языком для машинного обучения.

Ага. Ассоциативные массивы часто используют в динамически типизированных языках.
В D, как правило, можно обойтись более эффективным контейнером.
Структура вместо ассоциативного массива будет существенно эффективнее. Она аллоцируется на стеке. Кроме того, компилятор может делать проверки, которые не доступны при использовании словаря. Например в случае опечаток.
Ещё код можно сделать нагляднее и читабельнее, если используемые структуры данных заранее определить:


struct Dpt18Decoded
{
    ubyte learn;
    ubyte number;
}
// ...
Dpt18Decoded foo()
{
    return Dpt18Decoded( (raw[0] & 0x80) >> 7, raw[0] | 0x7f );
}

В статье не хватает подсветки синтаксиса — так текст будет восприниматься легче.


Несколько замечаний по коду:


Не нужно заранее делать массив больше, но зарезервировать память действительно хорошая практика.
Для этого есть метод reserve:


res.reserve(count);

Ещё есть статические массивы. Для них не нужны аллокации в кучи. Если размер массива известен на этапе компиляции, то использование такого массива может сделать программу эффективнее.


По коду, обратил внимание, что вы используете словари там, где достаточно было бы кортежей (tuple) или структур.

Конечно. Но иногда этого недостаточно. Поэтому придумали тесты, valgrind, контракты и прочие проверки времени выполнения.

Так в итоге, для примера выше — компилятор поймёт, что n не 7, а 6 при выходе из функции?

Да, конечно.


И в чём тогда польза?

вот:


какую пользу дают контракты:
  • Улучшают читаемость кода за счёт явного документирования.
  • Повышают надёжность кода, дополняя собой тестирование.
  • Позволяют компиляторам использовать низкоуровневые оптимизации и генерировать более быстрый код.

хочу понять, как компилятор определит, что контракт не выполнен

При проверке постусловия не анализируется что происходит в теле функции. Просто проверяется предикат с теми значениями, которые получились при выходе из функции.


Ну тогда тут логика Хоара вообще не при чём

Про логику Хоара я упомянул чтобы было понятно откуда вообще контракты взялись и заинтересовавшиеся смогли изучить вопрос более глубоко.


Контракты предполагают несколько непривычный стиль написания программы. Поэтому я счёл разумным более детально описать мотивацию.


Стандарт не накладывает на компиляторы обязанность проверять корректность всей программы по контрактам. И программист может не описывать контракты для вообще всех функций в программе. Это допустимо. Но если всё же все контракты описаны, то проверить программу по логике Хоара возможно. Но не с помощью компилятора.

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

Верификация во время выполнения должна отрабатывать на тестовом стенде. В проде проверки вообще желательно отключать.

Ещё не совсем понял один момент: чтобы проверять мои вызовы к либе на валидность, мне придётся её тоже собрать в debug?

Да. Нужна будет отдельная сборка либы.

3 Совершенно неясен вопрос с семантикой

Такой пример не скомпилируется.
Если n определён в аргументах функции, то нельзя его переопределить.
Видимо вы имели ввиду вот такой пример


int foo(int n)
    [[ expects:   n == 5 ]]
    [[ ensures n: n == 7 ]]
{
    int *p = &n;
    *p = 7;
    return n;
}

Нет никаких проблем. n в ensures будет идентификатором возвращаемого значения.
Хотя, конечно, так лучше не делать т.к. страдает читаемость кода


5 Ещё про семантику: как реально компилятор будет проверять соблюдение контрактов? Нужна семантика, чтобы порождать условия корректности, а потом их доказывать.

Я думаю компиляторы не будут заниматься формальным доказательством корректности программы по контрактам. Такие инструменты, наверное, можно будет сделать. Но это не задача компилятора. Задача компилятора просто проверить соблюдение контракта для каждой отдельно взятой функции и что-то сделать, в зависимости от настроек сборки. Например, вызывать std::terminate или violation_handler.

Если они вам не нравятся, можете их не использовать. Не вижу чем они портят язык.

Кажется понял о чём вы спрашиваете.
Если неправильные аргументы являются частью нормального потока выполнения программы, то контракты не подходят для проверки.
Нужно либо изменить архитектуру, либо отказаться от контрактов.
Т.е. когда в функцию пришёл аргумент, нарушающий контракт, то программа должна тут же завершиться.
Поэтому, при использовании контрактов, вызывающая сторона должна провести всю необходимую валидацию. А контракты просто проверяют корректность валидации.

В контракте нельзя рассчитывать на какие то вычисления. Если нужно, чтобы вычисления гарантированно производились всегда, то нужно выносить их отдельно от контракта.
Кроме того, в предикатах контрактов не должно быть побочных эффектов.
Если вычисления VERIFY() нужны только для проверки и больше ничего и не имеют побочных эффектов, то можно внести их в контракт.

Если я правильно понял ваш вопрос, то ответ — нет. Контракты не предназначены для ветвления. Только проверки. Причём функция должна работать также, как если бы контрактов вовсе не было.
По поводу


только для заданных до компиляции значений

Если функция, не constexpr, то она может ссылаться на не-constexpr локальные переменные из своей области видимости (есть нюанс с приватными и защищёнными полями класса).
Например:


int a = 1;
int foo(int n) [[ expects: a <= n ]];

Функция не-constexpr — может ссылаться на не-constexpr переменную.

Конкретно в случае с assert и, если говорить только о внешнем виде, то — дело вкуса. Мне лично [[assert: z >= 0]] больше нравится.
Если появляется ещё и предусловие, то вариант из стандарта уже становится чуть нагляднее, а если появляется ещё и постусловие и несколько точек выхода из функции, то разница становится очевидной. Кроме того, макросы нельзя сделать частью интерфейса. Нельзя их поместить в заголовочный файл отдельно от реализации.

Раз уж написали про Яндекс, надо было упомянуть и Рамблер. В 1998-99 годах Рамблер был более популярным поисковиком и сервисом чем Яндекс.
Я помню то время, когда люди видели открытое окно Яндекса и недоумевали:
— Что ещё за Яндекс, есть же Рамблер.
А потому у них что-то пошло не так.
Мне почему то запомнилась какая-то кадровая рокировка между этими сервисами в результате которой один поднялся, а другой опустился, но вот что за ракировака сейчас не вспомню.

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

Information

Rating
11,018-th
Location
Уфа, Башкортостан(Башкирия), Россия
Date of birth
Registered
Activity