ch
Feedback
PascalABC.NET официальный канал

PascalABC.NET официальный канал

前往频道在 Telegram

Официальный канал языка и системы программирования PascalABC.NET

显示更多
1 864
订阅者
-624 小时
-57 天
-2330 天
帖子存档
RayTracer, поправленный ИИ Давний пример, публиковался здесь. Попросил ИИ его ускорить. Ускорил в 10 раз https://gist.github.
RayTracer, поправленный ИИ Давний пример, публиковался здесь. Попросил ИИ его ускорить. Ускорил в 10 раз https://gist.github.com/miks1965/592a9ee7a812cafa89dde0440b8ee9a3 Сейчас эта сцена рендерится за 0.3 сек. Чтож, спасибо, Claude!

Расширение PascalABC.NET для VS Code на Mac — работает! 🍎 Доступна версия 0.5.1 расширения PascalABC.NET для Visual Studio C
Расширение PascalABC.NET для VS Code на Mac — работает! 🍎 Доступна версия 0.5.1 расширения PascalABC.NET для Visual Studio Code. На macOS уже работают: ✅ запуск программ ✅ подсветка синтаксиса ✅ IntelliSense — автодополнение и информация о символах Скачать расширение можно здесь: https://pascalabc.net/vscode/

PascalABC․NET + VS Code + .NET 10 В PascalABC․NET 4.0 появился официальный плагин для Visual Studio Code. Он поддерживает: ◉
PascalABC․NET + VS Code + .NET 10 В PascalABC․NET 4.0 появился официальный плагин для Visual Studio Code. Он поддерживает: ◉ компиляцию и запуск программ; ◉ IntelliSense; ◉ диагностику ошибок; ◉ подсказки типов и параметров; ◉ .NET Framework 4.8 и .NET 10. С .NET 10 PascalABC․NET можно использовать в VS Code на Windows, Linux и macOS. На скриншоте — PascalABC․NET в VS Code с работающим IntelliSense и запуском программы под .NET 10.

🚀 Предварительная версия PascalABC․NET 4.0.1 уже доступна На странице скачивания PascalABC․NET появился новый раздел — «Пред
🚀 Предварительная версия PascalABC․NET 4.0.1 уже доступна На странице скачивания PascalABC․NET появился новый раздел — «Предварительная версия». Сейчас в нём доступна PascalABC․NET 4.0.1 Beta. Именно эта версия будет постепенно накапливать новые возможности и последние исправления. По мере готовности она станет основной версией PascalABC․NET, а пока её можно использовать для знакомства с нововведениями и тестирования. Сейчас доступны: — StandardPack 4.0.1 Beta — консольный компилятор 4.0.1 Beta для .NET 10 — список изменений в 4.0.1 Скачать предварительную версию: https://pascalabc.net/ssyilki-dlya-skachivaniya/

🎓 ML PascalABC․NET — машинное обучение без внешних зависимостей Одно из главных нововведений PascalABC.NET 4.0 — новая библи
🎓 ML PascalABC․NET — машинное обучение без внешних зависимостей Одно из главных нововведений PascalABC.NET 4.0 — новая библиотека ML PascalABC․NET. Это уже не набор отдельных учебных алгоритмов, а целостная библиотека для анализа данных и классического машинного обучения. В ней есть всё необходимое для полного ML-процесса: ● работа с табличными данными (DataFrame), статистика и визуализация ● подготовка признаков: пропуски, кодирование категорий, масштабирование ● классификация и регрессия: Logistic Regression, kNN, Decision Tree, Random Forest, Gradient Boosting ● кластеризация: KMeans и DBSCAN ● метрики, разбиение выборок и кросс-валидация ● ML-конвейеры для объединения подготовки данных и моделей ● встроенные датасеты для обучения и экспериментов API библиотеки построен вокруг привычной современной схемы Fit / Transform / Predict. По организации работы и удобству программирования ML PascalABC.NET следует подходам scikit-learn, оставаясь при этом нативной библиотекой PascalABC․NET. И принципиальный момент — никаких внешних зависимостей. DataFrame, линейная алгебра, модели, препроцессинг, метрики и валидация реализованы непосредственно в экосистеме PascalABC․NET. Мы подготовили отдельный сайт с документацией, обучающими материалами и примерами: ML PascalABC.NET — документация и обучение Если вы хотите познакомиться с машинным обучением на PascalABC․NET, теперь для этого есть полноценная среда — от загрузки и подготовки данных до обучения модели и оценки её качества.

🎓 С Днём знаний! Поздравляем всех подписчиков канала PascalABC․NET с началом нового учебного года! К 1 сентября у PascalABC․
🎓 С Днём знаний! Поздравляем всех подписчиков канала PascalABC․NET с началом нового учебного года! К 1 сентября у PascalABC․NET сразу несколько важных обновлений. Новый сайт pascalabc.net. Современный дизайн, новая структура и удобный доступ к материалам о системе, документации и обучении. Заходите, смотрите и делитесь впечатлениями в комментариях! PascalABC․NET 4.0. ● В новой версии появилась собственная библиотека ML PascalABC․NET для машинного обучения — без внешних зависимостей. Теперь задачи анализа данных и классического машинного обучения можно решать средствами самого PascalABC․NET. ● Ещё одно важное обновление — компилятор для .NET 10.0. С 1 сентября! Успешного и интересного учебного года!

У официального канала PascalABC.NET появилось зеркало в MAX: https://max.ru/channel_pabc_official Оба канала заработают полным ходом с сентября. Появилась также группа для обсуждения в MAX вот с такой красивой пригласительной ссылкой https://max.ru/join/D28ks-E4Olzc7BN7mVlAqhNr-NXbgijzaRnGNQ9FXZQ Она также полноценно заработает с сентября. Кому удобнее обсуждать в MAX - присоединяйтесь!

Вычисление выражений с помощью Eval В модуле Utils появилась стандартная функция Eval позволяющая вычислять арифметические вы
Вычисление выражений с помощью Eval В модуле Utils появилась стандартная функция Eval позволяющая вычислять арифметические выражения, заданные в виде строки Выражение например можно ввести с клавиатуры
uses Utils;

begin
  Println(Eval('2 + 3 * 4'));
  Println(Eval('(2.4 + 3 % 2) * 6 - 1'));
  Println(Eval('(5 > 3) and (2 < 4)'));
  Println(Eval('IIF(17 % 2 = 0, ''even'', ''odd'')'));
  Println(Eval('Len(''PascalABC.NET'')'));
  
  var i := EvalInt('2 + 3');
  var x := EvalReal('10 / 4.0');
  var b := EvalBool('(10 >= 5) and (3 <> 4)');
  var s := EvalStr('''PascalABC'' + ''.NET''');
  
  Println(i, x, b, s)
end.

Запомним этот день и час Все тесты под .NET 10 прошли. Консольный компилятор работает! 01.08.2026 г. 21.54
Запомним этот день и час Все тесты под .NET 10 прошли. Консольный компилятор работает! 01.08.2026 г. 21.54

Понятно из-за чего - двумерные Generic-массивы. Попросил Codex разобраться. И тут - произошла потрясающая вещь! Codex нашел о
Понятно из-за чего - двумерные Generic-массивы. Попросил Codex разобраться. И тут - произошла потрясающая вещь! Codex нашел ошибку не в PascalABC.NET, а в Runtime .Net 9.0! Причем, Codex сам проверил, что на компьютере установлен Runtime .NET 10.0, откомпилировал пример под ней и убедился, что он работает! Программист пытался бы исправить ошибку, предполагая что она внутри PascalABC.NET, потратив на это безрезультатно неопределенное время... Даже не знаю, что еще говорить... Одни эмоции ) Нет, знаю :) Следующим запросом я попросил перевести весь проект под .NET 10.0. Codex любезно согласился, попросил сделать коммит на Github от греха, пошуршал, ответил вот это: =============================== Проект переведён на .NET 10. Изменено: целевая платформа, каталог bin\net10 и символ NET10_0 в [Directory.Build.props (line 5)](D:/PABC_Console_Git_NET9/Directory.Build.props:5); автоматическое копирование Lib, Lng, Ico и Highlighting из bin\shared; генерируемые runtimeconfig.json теперь используют .NET 10 в [NETGenerator.cs (line 205)](D:/PABC_Console_Git_NET9/src/NETGenerator/NETGenerator.cs:205); исправлено падение MarkSequencePoint без отладочного документа в [NETGenerator.cs (line 319)](D:/PABC_Console_Git_NET9/src/NETGenerator/NETGenerator.cs:319); TestRunner переключён на bin\net10 в [runtests.bat (line 1)](D:/PABC_Console_Git_NET9/TestSuite/runtests.bat:1); обновлён README. =================== То есть сделал больше чем от него ожидалось - не только перевел проект под .NET 10, но и автоматически создал для него папку, нашел на компьютере и скопировал дополнительные файлы, необходимые для запуска, проверил, что запускаются старые тесты, исправил за компанию еще одну ошибку с MarkSequencePoint, обновил ReadMe где упоминалось что используется .NET 9, и порекомендовал установить VS 2026. Уф... Ощущения - Codex-агент - это такой джинн из бутылки, который является опытным программистом и за токены делает крайне нетривиальные действия и дает советы. Что ж - пишите комментарии!

PascalABC.NET под net 9 и Codex Как знают читатели нашего канала, мы давно пытаемся перевести консольный компилятор PascalABC
PascalABC.NET под net 9 и Codex Как знают читатели нашего канала, мы давно пытаемся перевести консольный компилятор PascalABC.NET с .NET Framework под современный .NET. С версии .NET 9.0 это стало возможно - появилась возможность генерировать сборку и сохранять ее на диск. Примерно год назад нам удалось создать компилирующийся проект консольного компилятора - в нем проходило примерно 95% наших тестов. Но некоторые тесты падали из-за различий в NET Framework и .NET 9.0. Этот год мы собирались с духом чтобы начать их исправлять. И вот - возникла идея загрузить проект в Codex и пообщаться с ним, как можно исправить некоторые ошибки. В этом посте делюсь, как была исправлена одна. Вот этот код
type 
  Days = (Mon,Tue,Wed,Thi,Fri,Sat);  

begin
  var ld := new List<Days>;  
end.
падал на строке
il.Emit(OpCodes.Newobj, cnstr);
которая генерировала IL код вызова конструктора List. Понятно, что дело именно в нашем пользовательском типе enum Days, потому что на других типах всё работает. И вот - вишенка на торте - проект загружен в Codex и после пары запросов с просьбой исследовать проект и главный файл генерации IL-кода я загрузил код падающего теста и задал вопрос, можно ли исправить ошибку. Полминуты. Да-да, CODEX думал ровно полминуты. И затем выдал: Ошибка исправлена в NETGenerator.cs (line 2665) Всё! Ошеломленный, я пообщался еще с Codex о причине ошибки: Но PersistedAssemblyBuilder в .NET 9 при выполнении:
il.Emit(OpCodes.Newobj, cnstr);
пытается найти исходное metadata-определение .ctor. Для generic-типа с аргументом EnumBuilder он этого сделать не может и выдаёт:
A MemberInfo that matches '.ctor' could not be found
При этом внутри EnumBuilder уже существует настоящий TypeBuilder, описывающий создаваемое перечисление. Исправление состоит в том, чтобы при формировании generic-типа передавать именно его. Но - основная интрига прямо сейчас. Год - страх человека исправить непростую ошибку из за отсутствия отсутствие нормальной документации. И полминуты на исправление ошибки ИИ-агентом.

📌 ЕГЭ по информатике: задача №3 в новой версии PascalABC.NET В преддверии ЕГЭ по информатике покажем, как можно решать задач
📌 ЕГЭ по информатике: задача №3 в новой версии PascalABC.NET В преддверии ЕГЭ по информатике покажем, как можно решать задачу №3 из демо варианта с помощью новых возможностей PascalABC.NET. Задача №3 обычно связана с поиском данных в таблицах: нужно объединить несколько листов, отфильтровать строки по условиям и посчитать итоговую величину. В новой версии PascalABC.NET это можно сделать в стиле современных инструментов анализа данных — через DataFrame.
uses MLABC;

begin
  var movement := DataFrame.FromODS('DEMO_3.ods', 'Движение_товаров');
  var goods := DataFrame.FromODS('DEMO_3.ods', 'Товар');
  var shops := DataFrame.FromODS('DEMO_3.ods', 'Магазин');

  var d1 := new DateTime(2024, 10, 5);
  var d2 := new DateTime(2024, 10, 14);
  
  var df := movement
    .Join(goods, 'Артикул')
    .Join(shops, 'ID магазина');
    
  var answer :=
    df.Filter(r ->
        (r['Наименование товара'] = 'Варенец термостатный') and
        (r['Район'] = 'Нагорный') and
        (r['Тип операции'] = 'Продажа') and
        (r['Дата'] >= d1) and
        (r['Дата'] <= d2)
      )
      .Sum(r ->
        r['Количество упаковок, шт'] *
        r['Цена за упаковку']
      );
  
  Println(answer);
end.
Что здесь происходит: 1️⃣ Загружаем три таблицы из ODS-файла: движение товаров, список товаров и список магазинов. 2️⃣ Объединяем таблицы:
movement
  .Join(goods, 'Артикул')
  .Join(shops, 'ID магазина')
После этого в одной таблице оказываются и данные о продажах, и названия товаров, и районы магазинов. 3️⃣ Фильтруем только нужные строки: товар — Варенец термостатный; район — Нагорный; операция — Продажа; дата — с 5 по 14 октября 2024 года включительно. 4️⃣ Считаем итоговую сумму продаж:
Количество упаковок * Цена за упаковку
и суммируем по всем найденным строкам. Такой код хорошо показывает, что PascalABC.NET развивается не только как учебный язык программирования, но и как удобная среда для работы с таблицами, данными и задачами анализа информации. Задача №3 ЕГЭ становится не набором ручных действий в электронных таблицах, а понятной программой: загрузили данные, объединили таблицы, отфильтровали, посчитали ответ. 🚀 PascalABC.NET — современное программирование для школы, ЕГЭ и реальных задач анализа данных. Скачайте последнюю версию!

В DataFrameABC появился тип DateTime В табличных данных часто встречаются столбцы с датами: дата регистрации, время создания
В DataFrameABC появился тип DateTime В табличных данных часто встречаются столбцы с датами: дата регистрации, время создания заказа, момент события в логе и т.д. Теперь в DataFrameABC для таких данных есть отдельный тип столбца:
ColumnType.ctDateTime
Это значит, что дату и время можно хранить не как строку, а как полноценное значение DateTime.
uses MLABC;

begin
  var text := '''
id,created_at,name
1,2024-01-15,Alice
2,2024-01-16 12:30:00,Bob
''';

  var schema := new Dictionary<string, ColumnType>;
  schema['created_at'] := ColumnType.ctDateTime;

  var df1 := CsvLoader.LoadFromLines(
    text.ToLines,
    schema := schema
  );

  Println('Явная схема:');
  df1.Print;
  Println(df1.DateTime('created_at')[0].Year);

  var df2 := CsvLoader.LoadFromLines(
    text.ToLines,
    inferTypes := True
  );

  Println;
  Println('Автоопределение:');
  df2.Print(dateTimeFormat := 'dd.MM.yy');
  Println(df2.GetColumnType('created_at'));
end.
В первом случае тип столбца задаётся явно через схему:
schema['created_at'] := ColumnType.ctDateTime;
После этого к значениям можно обращаться как к DateTime:
df1.DateTime('created_at')[0].Year
Во втором случае используется автоопределение типов:
inferTypes := True
CsvLoader сам распознаёт столбец created_at как дату и время. При выводе можно задать формат отображения:
df2.Print(dateTimeFormat := 'dd.MM.yy');
Тип DateTime делает работу с временными данными в DataFrameABC более естественной: даты больше не нужно хранить как обычные строки, а значит, их можно корректно обрабатывать, форматировать и использовать дальше при подготовке данных для анализа и машинного обучения.

7 июня на мехмате ЮФУ состоялось награждение победителей и призёров олимпиады PascalABC.NET 2026. Поздравляем всех участников
7 июня на мехмате ЮФУ состоялось награждение победителей и призёров олимпиады PascalABC.NET 2026. Поздравляем всех участников, победителей и призёров! Для школьников 10–11 классов эта олимпиада имеет и практическое значение: победители и призёры, поступающие на мехмат ЮФУ, получат дополнительно 10 баллов к суммарному баллу ЕГЭ. Отдельно отметим, что ряд задач был специально ориентирован на лаконичные решения на PascalABC.NET. Многие участники успешно воспользовались выразительными возможностями языка и показали, что короткая программа вполне может быть точной, понятной и эффективной. Желаем ребятам дальнейших успехов в программировании и ждём новых участников в следующем году!

Конкатенация DataFrame-ов в MLABC
uses MLABC;

begin
  var df1 := DataFrame.FromCsvText('''
id,name,age
1,Ann,10
2,Bob,12
''');

  var df2 := DataFrame.FromCsvText('''
id,name,age
3,Cat,11
4,Dan,13
''');

  var df := DataFrame.Concat(df1, df2);
  df.Print;
end.
Результат
┌────┬──────┬─────┐
│ id │ name │ age │
├────┼──────┼─────┤
│ 1  │ Ann  │ 10  │
│ 2  │ Bob  │ 12  │
│ 3  │ Cat  │ 11  │
│ 4  │ Dan  │ 13  │
└────┴──────┴─────┘
DataFrame.Concat выполняет вертикальную конкатенацию датафреймов с обязательной проверкой схемы. Проверяются: - количество столбцов; - имена столбцов; - порядок столбцов; - типы данных. Если схемы несовместимы — будет сгенерировано исключение. Это защищает от случайного объединения несовместимых таблиц и делает работу с данными более предсказуемой и безопасной. Всё как в pandas только лучше :)

Олимпиада PascalABC.NET 2026 16 мая прошла олимпиада по программированию Мехмат - PascalABC.NET 2026 В ней приняло участие 49
Олимпиада PascalABC.NET 2026 16 мая прошла олимпиада по программированию Мехмат - PascalABC.NET 2026 В ней приняло участие 49 школьников Ростова и области Приводим задачу C1 и ее решение
begin
  var words := ReadString.ToWords;
  Print(words.GroupBy(w -> w.Order.JoinToString).Max(g -> g.Count));
end.

Простой текстовый редактор в GraphWPF uses GraphWPF; var (x,y) := (0.0,0.0); procedure KeyPress(c: char); begin if c = ' ' th
Простой текстовый редактор в GraphWPF
uses GraphWPF;

var (x,y) := (0.0,0.0);

procedure KeyPress(c: char);
begin
  if c = ' ' then
    c := Chr($A0);
  TextOut(x,y,c);
  x += TextWidth(c);
end;

procedure KeyDown(k: Key);
begin
  case k of
    Key.Enter: begin
      x := 0;
      y += TextHeight('q');
    end;
    Key.Back: if x > 0 then
    begin
      x -= TextWidth('n');
      FillRectangle(x,y,TextWidth('n'),TextHeight('n'));
    end;
  end;
end;

begin
  Font.Size := 20;
  Font.Name := 'Consolas';
  OnKeyPress := KeyPress;
  OnKeyDown := KeyDown;
end.
Демонстрация событий клавиатуры в GraphWPF для создания игрушечного текстового редактора. Можно набирать текст, стирать последний символ, используя BackSpace, и переходить на следующую строку

Табличная предобработка: Imputer и OrdinalEncoder Один из важных этапов работы с табличными данными — предобработка: заполнен
Табличная предобработка: Imputer и OrdinalEncoder Один из важных этапов работы с табличными данными — предобработка: заполнение пропусков, кодирование категориальных признаков, масштабирование числовых данных и другие преобразования. Пример: сначала заполним пропуск в числовом столбце population средним значением, а затем закодируем категориальный столбец region числами.
uses MLABC;

begin
  var df := DataFrame.FromCsvText('''
city,population,region
Ростов-на-Дону,1142,Юг
Таганрог,NA,Юг
Воронеж,1058,Центр
Курск,452,Центр
Белгород,392,Центр
''');

  Println('Исходные данные:');
  df.Print;
  Println;

  // Заполняем пропуск в числовом столбце средним значением
  var imputer := new Imputer(['population']);
  df := imputer.FitTransform(df);

  // Кодируем названия регионов числами 0, 1, 2, ...
  var encoder := new OrdinalEncoder('region');
  df := encoder.FitTransform(df);

  Println('После Imputer и OrdinalEncoder:');
  df.Print;
end.
Вывод:
Исходные данные:
          city  population  region 
Ростов-на-Дону        1142      Юг 
      Таганрог          NA      Юг 
       Воронеж        1058   Центр 
         Курск         452   Центр 
      Белгород         392   Центр 

После Imputer и OrdinalEncoder:
          city  population  region 
Ростов-на-Дону     1142.00       0 
      Таганрог      761.00       0 
       Воронеж     1058.00       1 
         Курск      452.00       1 
      Белгород      392.00       1 
Imputer анализирует данные на этапе Fit и запоминает значение, которым нужно заменить пропуски. В данном примере для столбца population используется среднее значение. OrdinalEncoder преобразует строковые категории в числовые коды: разные значения столбца region получают номера 0, 1, 2, ... Такой подход реализует привычную для ML-библиотек схему Fit/Transform: сначала объект настраивается по данным, затем применяет преобразование к таблице. #MLABC

Табличная предобработка: Imputer и OrdinalEncoder Один из важных этапов работы с табличными данными — предобработка: заполнен
Табличная предобработка: Imputer и OrdinalEncoder Один из важных этапов работы с табличными данными — предобработка: заполнение пропусков, кодирование категориальных признаков, масштабирование числовых данных и другие преобразования. Пример: сначала заполним пропуск в числовом столбце population средним значением, а затем закодируем категориальный столбец region числами.
uses MLABC;

begin
  var df := DataFrame.FromCsvText('''
city,population,region
Ростов-на-Дону,1142,Юг
Таганрог,NA,Юг
Воронеж,1058,Центр
Курск,452,Центр
Белгород,392,Центр
''');

  Println('Исходные данные:');
  df.Print;
  Println;

  // Заполняем пропуск в числовом столбце средним значением
  var imputer := new Imputer(['population']);
  df := imputer.FitTransform(df);

  // Кодируем названия регионов числами 0, 1, 2, ...
  var encoder := new OrdinalEncoder('region');
  df := encoder.FitTransform(df);

  Println('После Imputer и OrdinalEncoder:');
  df.Print;
end.
Вывод: Исходные данные: city population region Ростов-на-Дону 1142 Юг Таганрог NA Юг Воронеж 1058 Центр Курск 452 Центр Белгород 392 Центр После Imputer и OrdinalEncoder: city population region Ростов-на-Дону 1142.00 0 Таганрог 761.00 0 Воронеж 1058.00 1 Курск 452.00 1 Белгород 392.00 1 Imputer анализирует данные на этапе Fit и запоминает значение, которым нужно заменить пропуски. В данном примере для столбца population используется среднее значение. OrdinalEncoder преобразует строковые категории в числовые коды: разные значения столбца region получают номера 0, 1, 2, ... Такой подход реализует привычную для ML-библиотек схему Fit/Transform: сначала объект настраивается по данным, затем применяет преобразование к таблице.

Не надо слов, не надо паники (это мой последний день на Титанике 🚢) В новой библиотеке ML для PascalABC.NET появился встроен
Не надо слов, не надо паники (это мой последний день на Титанике 🚢) В новой библиотеке ML для PascalABC.NET появился встроенный датасет TitanicRu — классическая задача бинарной классификации: предсказать, выжил пассажир или нет. Причём поля датасета уже русифицированы: ● ВозрастПолКлассЦенаБилетаПортПосадкиВыжил и т.д. Ниже — полный пример ML pipeline: ● загрузка датасета, ● обработка пропусков, ● кодирование категориальных признаков, ● разделение train/test, ● нормализация, ● обучение моделей, ● сравнение качества.
uses MLABC;

begin
  var ds := Datasets.TitanicRu;
  var df := ds.Data.Drop(['Id', 'Имя']);

  // Заполняем пропуски
  var ageImputer := new Imputer(['Возраст']);
  df := ageImputer.FitTransform(df);

  var portImputer := new Imputer('Саутгемптон', ['ПортПосадки']);
  df := portImputer.FitTransform(df);

  // Кодируем категориальные признаки числами.
  var sexEncoder := new LabelEncoder('Пол');
  df := sexEncoder.FitTransform(df);

  var portEncoder := new LabelEncoder('ПортПосадки');
  df := portEncoder.FitTransform(df);

  var features := ['Класс', 'Пол', 'Возраст', 'БратьяИСупруги',
    'РодителиИДети', 'ЦенаБилета', 'ПортПосадки'];

  var X := df.ToMatrix(features);
  var y := df.GetIntColumn('Выжил');

  var (Xtrain, Xtest, ytrain, ytest) :=
    Validation.TrainTestSplit(X, y, testRatio := 0.2, seed := 42);

  var scaler := new StandardScaler;
  scaler.Fit(Xtrain);

  var XtrainScaled := scaler.Transform(Xtrain);
  var XtestScaled := scaler.Transform(Xtest);

  var lr := new LogisticRegression(
    learningRate := 0.01,
    epochs := 2000
  );

  lr.Fit(XtrainScaled, ytrain);
  var predLR := lr.Predict(XtestScaled);

  var tree := new DecisionTreeClassifier(
    maxDepth := 5,
    minSamplesLeaf := 3,
    minSamplesSplit := 6
  );

  tree.Fit(Xtrain, ytrain);
  var predTree := tree.Predict(Xtest);

  var forest := new RandomForestClassifier(
    nTrees := 100,
    maxDepth := 6,
    minSamplesLeaf := 3,
    minSamplesSplit := 6
  );

  forest.Fit(Xtrain, ytrain);
  var predForest := forest.Predict(Xtest);

  Println('Сравнение моделей на TitanicRu');

  Println($'LogisticRegression:      Accuracy = {Metrics.Accuracy(ytest, predLR):F3}');
  Println($'DecisionTreeClassifier: Accuracy = {Metrics.Accuracy(ytest, predTree):F3}');
  Println($'RandomForestClassifier: Accuracy = {Metrics.Accuracy(ytest, predForest):F3}');
end.
Типичный результат:
LogisticRegression:    Accuracy = 0.787
DecisionTreeClassifier: Accuracy = 0.809
RandomForestClassifier: Accuracy = 0.831
Получается практически sklearn-style ML прямо в PascalABC.NET: ● ImputerLabelEncoderStandardScalerTrainTestSplitLogisticRegressionDecisionTreeClassifierRandomForestClassifierMetrics.Accuracy без внешних зависимостей и с полностью типизированным API.