Синтаксис и применение Механизм анализа данных в платформе 1С:Предприятие. Описание и примеры кода.
Полное описание, параметры и ограничения
Механизм анализа данных
Механизм представляется совокупностью объектов встроенного языка 1С:Предприятие. Схема взаимодействия основных объектов механизма показана на рисунке.
Объекты, которые могут быть использованы на сервере 1С:Предприятие отображены на схеме в блоках с белым фоном, объекты, используемые только на клиенте помещены в блоки с темным фоном.
Настройка колонок анализа данных – совокупность настроек входных колонок анализа данных. Для каждой колонки указывается тип данных, содержащихся в ней, роль выполняемая колонкой, дополнительные настройки, зависящие от типа производимого анализа.
Параметры анализа данных – набор параметров производимого анализа данных. Состав параметров зависит от типа анализа. Например, для кластерного анализа указывается количество кластеров, на которые необходимо разбить исходные объекты, тип измерения расстояния между объектами и т.п.
Исходные данные – источник данных для анализа. В качестве источника данных может выступать результат запроса, область ячеек табличного документа, таблица значений.
Анализатор – объект, непосредственно выполняющий анализ данных. Объекту устанавливается источник данных, задаются параметры. Результатом работы данного объекта является результат анализа данных, тип которого зависит от типа анализа.
Результат анализа данных – специальный объект, содержащий информацию о результате анализа. Для каждого вида анализа предусмотрен свой результат. Например, результатом анализа данных – дерево решения будет объект типа РезультатАнализаДанныхДеревоРешений. В дальнейшем результат может быть выведен в табличный документ при помощи построителя отчета анализа данных, может быть выведен посредством программного доступа к его содержимому, может быть использован для создания модели прогноза. Любой результат анализа данных может быть сохранен для последующего использования.
Модель прогноза – специальный объект, позволяющий выполнять прогноз на основании входных данных. Тип модели зависит от типа анализа данных. Например, модель, созданная для анализа данных – поиск ассоциаций будет иметь тип МодельПрогнозаПоискаАссоциаций. Такая модель сможет выдавать прогнозы типа: т.к. данный покупатель купил заданный набор товаров, то с определенно вероятностью он должен купить и другой набор товаров. На вход модели прогноза передается источник данных для прогноза. Результатом является таблица значений, содержащая прогнозируемые значения.
Выборка для прогноза – таблица значений, результат запроса или область табличного документа, содержащая информацию, по которой необходимо построить прогноза. Например, для модели прогноза – поиск ассоциаций, выборка может содержать перечень продуктов документа продажи. Результат же работы модели может рекомендовать, какие товары можно еще предложить покупателю.
Настройка колонок выборки – набор специальных объектов, показывающих соответствие между колонками модели прогноза и колонками выборки прогноза. Например, колонки модели прогноза с именем «Товар» может соответствовать колонка выборки «Номенклатура».
Настройка колонок результата — позволяет управлять тем, какие колонки будут помещены в результирующую таблицу модели прогноза. Например, для поиска ассоциаций мы можем вывести в результат номенклатуру, которую скорее всего приобретет клиент и вероятность подобной покупки.
Результат работы модели – таблица значений состоящая из колонок, как указано в настройках результирующих колонок и содержащая прогнозируемые данных. Конкретное содержимое определяется типом анализа.
Построитель отчета анализа данных – объект, позволяющий выводить отчет о результате анализа данных. Кроме того, построитель отчета предоставляет специальные объект для связи с данными, с тем, чтобы позволить пользователю интерактивно управлять параметрами анализа, настройкой колонок источника данных, настроек колонок модели прогноза и т.п.
Типы анализа
Механизм позволяет выполнять следующие виды анализа:
Общая статистика
Поиск ассоциаций
Поиск последовательностей
Дерево решений
Кластерный анализ
Практические примеры
Рассчитать ту же статистику на сервере без клиентского построителя
В отличие от построителя, АнализДанных.Выполнить возвращает результат напрямую; используется собственная таблица из четырёх строк.
Где и как запускать
Полный серверный общий модуль собственной учебной базы.
Подготовка
Собственная учебная база 8.5.1.1343, толстый клиент Windows. Создайте внешнюю обработку с управляемой формой, командой Выполнить и её кнопкой. Вставьте весь модуль выбранного урока.
Методы построителя отчёта доступны только толстому клиенту, хотя сам тип упомянут и в других контекстах. Не переносите этот полный модуль в тонкий/веб-клиент или серверный обработчик.
Для отдельного урока АнализДанных без построителя используется собственный серверный общий модуль УчебнаяСтатистика с флагом Сервер и вызов УчебнаяСтатистика.ВыполнитьПример() из серверной команды.
Все значения вымышлены и создаются в памяти. Нет чтения документов/платежей, сетевых моделей, персональных данных, записи базы, сохранения файлов или печати.
Это учебный расчёт на маленьком наборе. Он не даёт основания прогнозировать реальные продажи или принимать бизнес-решения без проверки качества исходных данных.
Процедура ВыполнитьПример() Экспорт
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Код", Новый ОписаниеТипов("Строка"));
Таблица.Колонки.Добавить("Регион", Новый ОписаниеТипов("Строка"));
Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
Для Номер = 1 По 4 Цикл
СтрокаТаблицы = Таблица.Добавить();
СтрокаТаблицы.Код = "guide-order-" + Строка(Номер);
СтрокаТаблицы.Регион = ?(Номер = 4, "Юг", "Север");
СтрокаТаблицы.Сумма = Номер * 100;
КонецЦикла;
Анализатор = Новый АнализДанных;
Анализатор.ТипАнализа = Тип("АнализДанныхОбщаяСтатистика");
Анализатор.ИсточникДанных = Таблица;
Настройки = Анализатор.НастройкаКолонок;
Код = Настройки.Найти("Код");
Регион = Настройки.Найти("Регион");
Сумма = Настройки.Найти("Сумма");
Если Код = Неопределено ИЛИ Регион = Неопределено ИЛИ Сумма = Неопределено Тогда
ВызватьИсключение "Анализатор не создал ожидаемые три настройки собственных колонок";
КонецЕсли;
Код.ТипКолонки = ТипКолонкиАнализаДанныхОбщаяСтатистика.Неиспользуемая;
Регион.ТипКолонки = ТипКолонкиАнализаДанныхОбщаяСтатистика.Входная;
Регион.ВидДанных = ВидДанныхАнализа.Дискретные;
Сумма.ТипКолонки = ТипКолонкиАнализаДанныхОбщаяСтатистика.Входная;
Сумма.ВидДанных = ВидДанныхАнализа.Непрерывные;
Результат = Анализатор.Выполнить();
Сообщить(ТипЗнч(Результат) = Тип("РезультатАнализаДанныхОбщаяСтатистика"));
Сообщить(Результат.КоличествоОбъектов = 4);
Сообщить(Результат.НепрерывныеПоля.Количество() = 1);
Сообщить(Результат.ДискретныеПоля.Количество() = 1);
Сообщить(Анализатор.НастройкаКолонок.Количество() = 3);
Сообщить("Параметров общей статистики: " + Строка(Анализатор.Параметры.Количество()));
КонецПроцедурыРазбор по шагам
Создаём АнализДанных, задаём тип анализа и собственную таблицу. Никакого клиентского табличного документа нет.
Настройки включают две колонки: Регион дискретный, Сумма непрерывная; Код исключён. Коллекция настроек при этом содержит все три исходные колонки.
Выполнить возвращает реальный результат. Не обращаемся к несуществующему Анализатор.Результат, как у построителя.
Проверяем тип результата, число объектов, размеры обоих массивов описаний и коллекции настроек.
Это серверный расчёт, а не обещание передачи ТаблицаЗначений в тонкий клиент. Наружу здесь выводятся только короткие сообщения.
Как проверить результат
Пять сравнений ожидаются Истина; количество параметров общей статистики диагностическое.
Не открывается окно отчёта, не выполняется вывод/печать на сервере.
Ожидаемый результат
Получен полный серверный вариант той же задачи с корректным возвращаемым значением анализатора.
На что обратить внимание
Клиентский построитель и серверный анализатор имеют разные контексты и контракты результата.
Не выполнять этот расчёт на реальных многомиллионных таблицах без оценки нагрузки и прерывания.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.
Обучить свое дерево на32 случаях и разобрать реальные классы, узлы и созданную модель
Полный серверный модуль создает собственную размеченную таблицу, назначает тип алгоритма и реальные параметры, получает результат и диагностирует все его свойства. Взвешенные классификации отделены от строк источника, дерево обходится без рекурсии, модель создается из результата без неизвестных объектов.
Где и как запускать
Полный серверный общий модуль УчебноеДеревоРешений85 собственной пустой конфигурации; отдельная управляемая форма получает только текст. В1С не выполнялся.
Подготовка
НОВАЯ отдельная пустая файловая база точно8.5.1.1343. Имя конфигурации УчебноеДеревоРешений85, совместимость Не использовать, Русский. Нет прикладных объектов, общих реквизитов, расширений, подписок, заданий или рабочих данных; модули конфигурации вручную пустые. Не использовать БП/КА2/УТ/УНФ.
Общие → Общие модули → УчебноеДеревоРешений85. Сервер=Да, Вызов сервера=Да, Клиент=Нет, Глобальный=Нет, Привилегированный=Нет. Вставить весь основной модуль, включая функции подготовки, проверки, обхода и защиты стенда. Будущая ручная подготовка: сохранить и обновить только собственную базу F7.
Собственная внешняя обработка УчебныйРасчетДерева85 → управляемая Форма → команда/кнопка Выполнить, действие Выполнить. Полный отдельный модуль формы ниже вызывает только собственный серверный общий модуль и получает текст отчета. Таблицы, алгоритм, узлы и модель на клиент не передаются.
Код в памяти создает32 строки: восемь повторений остатков0,1,10,11 с уникальными own-case-кодами. РешениеПоПравилу=Нужно для остатка<5, иначе Достаточно. Это вымышленные метки, иллюстрирующие уже заданное учебное правило, а не данные реальных продаж/заказов.
Код — НеИспользуемая колонка, Остаток — Входная с видом Непрерывные, РешениеПоПравилу — Прогнозируемая с видом Дискретные. МинимальноеКоличествоСлучаев1, МаксимальнаяГлубина4, ТипУпрощенияНеУпрощать. Имена параметров сверены с installed-справкой; их реально ищет созданный анализатор.
Никакие строки1С, модели в базе, файлы, печатные документы или сетевые сервисы не подготавливать. Нет рабочего источника, обучения нейросети, отправки данных наружу или автоматической закупки. Вывод основан только на текущем маленьком объекте памяти.
Функция ВыполнитьПример() Экспорт
ПроверитьСвойПустойСтенд();
Таблица = СоздатьСвоиСлучаи();
Анализатор = Новый АнализДанных;
Анализатор.ТипАнализа = Тип("АнализДанныхДеревоРешений");
Анализатор.ИсточникДанных = Таблица;
НастроитьСвоиКолонки(Анализатор.НастройкаКолонок);
НастроитьСвойПараметр(Анализатор.Параметры, "МинимальноеКоличествоСлучаев", 1);
НастроитьСвойПараметр(Анализатор.Параметры, "МаксимальнаяГлубина", 4);
НастроитьСвойПараметр(Анализатор.Параметры, "ТипУпрощения", ТипУпрощенияДереваРешений.НеУпрощать);
Результат = Анализатор.Выполнить();
Если ТипЗнч(Результат) <> Тип("РезультатАнализаДанныхДеревоРешений") Тогда
ВызватьИсключение "Не получен настоящий результат своего дерева решений";
КонецЕсли;
Если Результат.КоличествоОбъектов <> Таблица.Количество() Или Результат.КоличествоКлассов <> 2
Или Результат.КоличествоЛистьев < 1 Или Результат.КоличествоУзлов < Результат.КоличествоЛистьев
Или Результат.Глубина < 0 Или Результат.Ошибка < 0 Или Результат.Ошибка > 100 Тогда
ВызватьИсключение "Результат не согласован с собственными32 случаями и двумя метками";
КонецЕсли;
ПроверитьСвоиКолонкиРезультата(Результат.НастройкаКолонок);
ПроверитьСвойПараметр(Результат.Параметры, "МинимальноеКоличествоСлучаев", 1);
ПроверитьСвойПараметр(Результат.Параметры, "МаксимальнаяГлубина", 4);
ПроверитьСвойПараметр(Результат.Параметры, "ТипУпрощения", ТипУпрощенияДереваРешений.НеУпрощать);
Отчет = "СВОЙ УЧЕБНЫЙ РАСЧЕТ, НЕ ПРОГНОЗ РЕАЛЬНЫХ ЗАКУПОК" + Символы.ПС;
Отчет = Отчет + "Объектов: " + Строка(Результат.КоличествоОбъектов) + "; классов: " + Строка(Результат.КоличествоКлассов) + Символы.ПС;
Отчет = Отчет + "Узлов: " + Строка(Результат.КоличествоУзлов) + "; листьев: " + Строка(Результат.КоличествоЛистьев) + Символы.ПС;
Отчет = Отчет + "Глубина по платформе: " + Строка(Результат.Глубина) + "; ошибка дерева в процентах: " + Строка(Результат.Ошибка) + Символы.ПС;
Классификации = Результат.Классификации;
Если ТипЗнч(Классификации) <> Тип("ФиксированныйМассив") Или Классификации.Количество() = 0 Тогда
ВызватьИсключение "Нужен реальный непустой массив сгруппированных классификаций";
КонецЕсли;
ВсегоСлучаев = 0;
Для Каждого Классификация Из Классификации Цикл
Если ТипЗнч(Классификация) <> Тип("КлассификацияОбъектаАнализаДанных") Или Классификация.Количество < 0 Тогда
ВызватьИсключение "Не получена настоящая классификация собственных случаев";
КонецЕсли;
Факт = ОписатьСвойКласс(Классификация.Факт);
Прогноз = ОписатьСвойКласс(Классификация.Прогноз);
ВсегоСлучаев = ВсегоСлучаев + Классификация.Количество;
Отчет = Отчет + "Случаев: " + Строка(Классификация.Количество) + "; факт: " + Факт + "; прогноз: " + Прогноз + Символы.ПС;
КонецЦикла;
Если ВсегоСлучаев <> Таблица.Количество() Тогда
ВызватьИсключение "Сумма количества случаев классификаций не равна32";
КонецЕсли;
Корни = Результат.КорневыеУзлы;
СтатистикаУзлов = ОбойтиСвоиУзлы(Корни);
Если СтатистикаУзлов.Узлов <> Результат.КоличествоУзлов Или СтатистикаУзлов.Листьев <> Результат.КоличествоЛистьев Тогда
ВызватьИсключение "Независимый обход не совпал с числами узлов и листьев результата";
КонецЕсли;
Отчет = Отчет + СтатистикаУзлов.Отчет + Символы.ПС;
Модель = Результат.СоздатьМодельПрогноза();
Если ТипЗнч(Модель) <> Тип("МодельПрогнозаДеревоРешений") Тогда
ВызватьИсключение "Результат не создал настоящий объект модели прогноза";
КонецЕсли;
КорниМодели = Модель.КорневыеУзлы;
СтатистикаМодели = ОбойтиСвоиУзлы(КорниМодели);
Если СтатистикаМодели.Узлов <> СтатистикаУзлов.Узлов Или СтатистикаМодели.Листьев <> СтатистикаУзлов.Листьев Тогда
ВызватьИсключение "Модель и результат не согласованы по своей структуре дерева";
КонецЕсли;
Отчет = Отчет + "Модель действительно создана из собственного результата; ее корни обходятся. Прогноз на новых данных в этом уроке не выполнялся";
Возврат Отчет;
КонецФункции
Функция СоздатьСвоиСлучаи()
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Код", Новый ОписаниеТипов("Строка"));
Таблица.Колонки.Добавить("Остаток", Новый ОписаниеТипов("Число"));
Таблица.Колонки.Добавить("РешениеПоПравилу", Новый ОписаниеТипов("Строка"));
Остатки = Новый Массив;
Остатки.Добавить(0);
Остатки.Добавить(1);
Остатки.Добавить(10);
Остатки.Добавить(11);
Для Повтор = 1 По 8 Цикл
Для Каждого Остаток Из Остатки Цикл
СтрокаСлучая = Таблица.Добавить();
СтрокаСлучая.Код = "own-case-" + Строка(Повтор) + "-" + Строка(Остаток);
СтрокаСлучая.Остаток = Остаток;
СтрокаСлучая.РешениеПоПравилу = ?(Остаток < 5, "Нужно", "Достаточно");
КонецЦикла;
КонецЦикла;
Если Таблица.Количество() <> 32 Тогда
ВызватьИсключение "Нужны ровно32 собственных учебных случая";
КонецЕсли;
Возврат Таблица;
КонецФункции
Процедура НастроитьСвоиКолонки(Настройки)
Код = Настройки.Найти("Код");
Остаток = Настройки.Найти("Остаток");
КолонкаРешения = Настройки.Найти("РешениеПоПравилу");
Если Код = Неопределено Или Остаток = Неопределено Или КолонкаРешения = Неопределено Или Настройки.Количество() <> 3 Тогда
ВызватьИсключение "Анализатор должен создать настройки трех собственных колонок";
КонецЕсли;
Код.ТипКолонки = ТипКолонкиАнализаДанныхДеревоРешений.НеИспользуемая;
Остаток.ТипКолонки = ТипКолонкиАнализаДанныхДеревоРешений.Входная;
Остаток.ВидДанных = ВидДанныхАнализа.Непрерывные;
КолонкаРешения.ТипКолонки = ТипКолонкиАнализаДанныхДеревоРешений.Прогнозируемая;
КолонкаРешения.ВидДанных = ВидДанныхАнализа.Дискретные;
ПроверитьСвоиКолонкиРезультата(Настройки);
КонецПроцедуры
Процедура ПроверитьСвоиКолонкиРезультата(Настройки)
Если ТипЗнч(Настройки) <> Тип("КолонкиАнализаДанных") Или Настройки.Количество() <> 3 Тогда
ВызватьИсключение "Нужны настоящие три настройки колонок анализа";
КонецЕсли;
Код = Настройки.Найти("Код");
Остаток = Настройки.Найти("Остаток");
КолонкаРешения = Настройки.Найти("РешениеПоПравилу");
Если Код = Неопределено Или Остаток = Неопределено Или КолонкаРешения = Неопределено Тогда
ВызватьИсключение "Исчезла собственная колонка";
КонецЕсли;
Если Код.ТипКолонки <> ТипКолонкиАнализаДанныхДеревоРешений.НеИспользуемая
Или Остаток.ТипКолонки <> ТипКолонкиАнализаДанныхДеревоРешений.Входная
Или Остаток.ВидДанных <> ВидДанныхАнализа.Непрерывные
Или КолонкаРешения.ТипКолонки <> ТипКолонкиАнализаДанныхДеревоРешений.Прогнозируемая
Или КолонкаРешения.ВидДанных <> ВидДанныхАнализа.Дискретные Тогда
ВызватьИсключение "Перепутаны ключ, числовой вход или собственная метка класса";
КонецЕсли;
КонецПроцедуры
Функция НайтиСвойПараметр(Параметры, Имя)
Параметр = Параметры.Найти(Имя);
Если Параметр = Неопределено Или ТипЗнч(Параметр) <> Тип("ПараметрАнализаДанных") Тогда
ВызватьИсключение "Не найден собственный параметр алгоритма " + Имя;
КонецЕсли;
Индекс = Параметры.Индекс(Параметр);
Если Индекс < 0 Или Индекс >= Параметры.Количество() Тогда
ВызватьИсключение "Индекс настоящего параметра выходит за границы";
КонецЕсли;
ПоИндексу = Параметры.Получить(Индекс);
Если ПоИндексу.Имя <> Параметр.Имя Или ПоИндексу.Имя <> Имя Тогда
ВызватьИсключение "Найти и Получить не вернули один собственный параметр";
КонецЕсли;
Возврат Параметр;
КонецФункции
Процедура НастроитьСвойПараметр(Параметры, Имя, Значение)
Параметр = НайтиСвойПараметр(Параметры, Имя);
Если Не Параметр.ТипЗначения.СодержитТип(ТипЗнч(Значение)) Тогда
ВызватьИсключение "Тип значения не разрешен реальным параметром " + Имя;
КонецЕсли;
Параметр.Значение = Значение;
ПроверитьСвойПараметр(Параметры, Имя, Значение);
КонецПроцедуры
Процедура ПроверитьСвойПараметр(Параметры, Имя, Эталон)
Параметр = НайтиСвойПараметр(Параметры, Имя);
Если ТипЗнч(Параметр.Значение) <> ТипЗнч(Эталон) Или Параметр.Значение <> Эталон Тогда
ВызватьИсключение "Не совпал собственный параметр результата " + Имя;
КонецЕсли;
КонецПроцедуры
Функция ОписатьСвоеСвойство(Описание)
Если ТипЗнч(Описание) <> Тип("СвойствоОбъектаАнализаДанных") Тогда
ВызватьИсключение "Нужно реальное описание значения или условия собственного анализа";
КонецЕсли;
Возврат Описание.Имя + "; сравнение=" + Строка(Описание.ВидСравнения)
+ "; значение=" + Строка(Описание.Значение) + "; с=" + Строка(Описание.ЗначениеС) + "; по=" + Строка(Описание.ЗначениеПо);
КонецФункции
Функция ОписатьСвойКласс(Класс)
Если ТипЗнч(Класс) <> Тип("ОбъектАнализаДанных") Тогда
ВызватьИсключение "Нужен реальный объект факта, прогноза или решения";
КонецЕсли;
Свойства = Новый Структура("РешениеПоПравилу", Неопределено);
ЗаполнитьЗначенияСвойств(Свойства, Класс);
Описание = Свойства.РешениеПоПравилу;
Если Описание = Неопределено Тогда
ВызватьИсключение "У собственного класса отсутствует единственная прогнозируемая колонка";
КонецЕсли;
Если ТипЗнч(Описание) <> Тип("СвойствоОбъектаАнализаДанных") Или Описание.Имя <> "РешениеПоПравилу"
Или Описание.ВидСравнения <> ВидСравнения.Равно
Или ТипЗнч(Описание.Значение) <> Тип("Строка")
Или (Описание.Значение <> "Нужно" И Описание.Значение <> "Достаточно") Тогда
ВызватьИсключение "Факт или прогноз не описывает собственную метку класса";
КонецЕсли;
Возврат ОписатьСвоеСвойство(Описание);
КонецФункции
Функция ОписатьСвоеРешение(Решение)
Если ТипЗнч(Решение) <> Тип("РешениеАнализаДанных") Или Решение.КоличествоСлучаев < 0 Тогда
ВызватьИсключение "Нужно настоящее возможное решение собственного узла";
КонецЕсли;
Возврат ОписатьСвойКласс(Решение.Решение) + "; правильных случаев=" + Строка(Решение.КоличествоСлучаев)
+ "; вероятность как вернула платформа=" + Строка(Решение.Вероятность);
КонецФункции
Функция ОбойтиСвоиУзлы(Корни)
Если ТипЗнч(Корни) <> Тип("ФиксированныйМассив") Или Корни.Количество() = 0 Тогда
ВызватьИсключение "Нужны настоящие непустые корни собственного результата или модели";
КонецЕсли;
Стек = Новый Массив;
Для Каждого Корень Из Корни Цикл
Стек.Добавить(Новый Структура("Узел,Уровень", Корень, 0));
КонецЦикла;
КоличествоУзлов = 0;
КоличествоЛистьев = 0;
Отчет = "ОБХОД СОБСТВЕННЫХ УЗЛОВ" + Символы.ПС;
Пока Стек.Количество() > 0 Цикл
Индекс = Стек.Количество() - 1;
Кадр = Стек[Индекс];
Стек.Удалить(Индекс);
Узел = Кадр.Узел;
Если ТипЗнч(Узел) <> Тип("УзелДереваРешений") Или Кадр.Уровень > 64 Или КоличествоУзлов >= 128 Тогда
ВызватьИсключение "Свой маленький обход вышел за допустимые учебные границы";
КонецЕсли;
КоличествоУзлов = КоличествоУзлов + 1;
Отчет = Отчет + "Узел=" + Строка(КоличествоУзлов) + "; уровень обхода=" + Строка(Кадр.Уровень)
+ "; попало случаев=" + Строка(Узел.КоличествоСлучаев) + Символы.ПС;
Условие = Узел.Условие;
Если Условие <> Неопределено Тогда
Если ТипЗнч(Условие) <> Тип("ОбъектАнализаДанных") Тогда
ВызватьИсключение "Узел не вернул документированный объект условия";
КонецЕсли;
Свойства = Новый Структура("Остаток", Неопределено);
ЗаполнитьЗначенияСвойств(Свойства, Условие);
Если Свойства.Остаток <> Неопределено Тогда
Отчет = Отчет + "Условие своего числового входа: " + ОписатьСвоеСвойство(Свойства.Остаток) + Символы.ПС;
Иначе
Отчет = Отчет + "У этого узла нет описания условия по Остаток; выдуманная граница не подставлялась" + Символы.ПС;
КонецЕсли;
КонецЕсли;
Отчет = Отчет + "Лучшее решение: " + ОписатьСвоеРешение(Узел.Решение) + Символы.ПС;
ВсеРешения = Узел.ВсеРешения;
Если ТипЗнч(ВсеРешения) <> Тип("ФиксированныйМассив") Тогда
ВызватьИсключение "Нужен настоящий массив возможных решений узла";
КонецЕсли;
Для Каждого Возможное Из ВсеРешения Цикл
Отчет = Отчет + "Возможное решение: " + ОписатьСвоеРешение(Возможное) + Символы.ПС;
КонецЦикла;
Дети = Узел.Узлы;
Если ТипЗнч(Дети) <> Тип("ФиксированныйМассив") Тогда
ВызватьИсключение "Нужен настоящий массив вложенных узлов";
КонецЕсли;
Если Дети.Количество() = 0 Тогда
КоличествоЛистьев = КоличествоЛистьев + 1;
Иначе
Для Каждого Дочерний Из Дети Цикл
Стек.Добавить(Новый Структура("Узел,Уровень", Дочерний, Кадр.Уровень + 1));
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат Новый Структура("Узлов,Листьев,Отчет", КоличествоУзлов, КоличествоЛистьев, Отчет);
КонецФункции
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедурыУчебныйРасчетДерева85.Форма
Собственная внешняя обработка → управляемая Форма → Модуль
Полный клиент-серверный модуль формы, не клиентский расчет анализа данных.
&НаКлиенте
Процедура Выполнить(Команда)
Отчет = ВыполнитьНаСервере();
Сообщить(Отчет);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ВыполнитьНаСервере()
Возврат УчебноеДеревоРешений85.ВыполнитьПример();
КонецФункцииРазбор по шагам
Серверный guard проверяет отсутствие прикладных объектов, расширений и активной транзакции. СоздатьСвоиСлучаи возвращает реальную ТаблицаЗначений с32 явно размеченными строками, а не неизвестный Источник.
ТипАнализа — значение Тип("АнализДанныхДеревоРешений"), не строка или выдуманное перечисление. После назначения источника появляются реальные настройки колонок. Каждое Найти проверяется, три роли и два вида данных задаются и перечитываются.
Параметры создаются самим алгоритмом. НайтиСвойПараметр подтверждает настоящий ПараметрАнализаДанных, получает Индекс, проверяет границы и перечитывает его через Получить. ТипЗначения.СодержитТип проверяется до присваивания Значение; после расчета те же значения и типы сверяются через Результат.Параметры.
Выполнить возвращает настоящий РезультатАнализаДанныхДеревоРешений. КоличествоОбъектов сопоставляется с32 строками, КоличествоКлассов с двумя собственными метками; глубина, узлы, листья и ошибка выводятся фактически. Не обещается конкретная граница разделения, размер дерева или нулевая ошибка.
Классификации — ФиксированныйМассив сгруппированных пар Факт/Прогноз. Количество каждого элемента — вес случаев этой классификации. Складываем веса и сверяем с32, а не требуем32 элементов массива. Факт и Прогноз имеют тип ОбъектАнализаДанных, их динамическое свойство РешениеПоПравилу содержит отдельное СвойствоОбъектаАнализаДанных, не голую строку.
В собственную Структура копируется только совпадающее имя свойства без явного СписокСвойств. Поэтому у корневого условия без Остаток структура остается с Неопределено, а отсутствие не скрывается универсальным Попытка. Классовая метка обязательна; имя, сравнениеРавно, строковый тип и два допустимых значения проверяются.
ОписатьСвоеСвойство показывает настоящее Имя, ВидСравнения, Значение, ЗначениеС и ЗначениеПо. У равенства границы не выдаются за смысл сравнения; у числового условия диагностируются фактические значения интервала без выдуманного правила включения/исключения концов.
КорневыеУзлы обходятся собственным стеком Массив, без рекурсивного роста стека вызовов. Для каждого настоящего УзелДереваРешений используются количество случаев, условие, лучшее и все решения, дочерние узлы. Лист определяется отсутствием детей. Учебные ограничения128 узлов/64 уровня предотвращают неограниченный диагностический обход.
РешениеАнализаДанных содержит число верных случаев, вероятность и отдельный ОбъектАнализаДанных класса. Вероятность выводится как вернула платформа: без неподтвержденного умножения на100. Только Результат.Ошибка прямо объявлена в справке процентами.
Числа узлов и листьев вычисляются независимо обходом и сверяются с результатом. Уровень собственного обхода начинается с0; его нельзя автоматически приравнивать к Глубина по платформе без знания соглашения о нумерации.
СоздатьМодельПрогноза вызывается именно у собственного результата. Реальная МодельПрогнозаДеревоРешений используется: ее КорневыеУзлы также обходятся и сопоставляются с результатом. Это создание и проверка структуры, не уже выполненный прогноз на новых данных.
Как проверить результат
Будущий результат:32 объектов и2 класса, действительные параметры1/4/НеУпрощать, отчет по сгруппированным факт/прогноз и реальным узлам. Сумма весов классификаций32; независимые числа узлов/листьев совпадают с результатом и созданной моделью. Значения глубины, ошибки и вероятностей не подставляются вручную.
Будущий отрицательный контроль данных: в СоздатьСвоиСлучаи заменить число повторений8 на7. Проверка собственного источника должна отклонить28 вместо32 до выполнения алгоритма. Вернуть8 после опыта.
Будущий отрицательный контроль ролей: только в НастроитьСвоиКолонки заменить роль Остаток сВходная наНеИспользуемая. ПроверитьСвоиКолонкиРезультата должен отвергнуть схему до расчета. Эталон проверяющей процедуры не изменять, затем вернуть исходную роль.
Будущий отрицательный контроль результата: только сразу после Результат = Анализатор.Выполнить() присвоить Результат = Неопределено. Проверка точного native-типа должна остановиться до readonly-чтений. Затем вернуть полный исходный код.
runtimeVerifiedScenarios=0: алгоритм, модель, BSL, форма и база1С здесь не запускались. Статические проверки не являются доказательством построенного дерева, качества прогноза или успешного обучения. Описан будущий опыт только собственной пустой базы.
Ожидаемый результат
Собственный полный учебный конвейер связывает реальные данные памяти, параметры, результат, группировки, граф дерева и созданную модель; все диагностические числа берутся из полученных объектов.
На что обратить внимание
У результатов, классификаций, узлов, решений и описаний свойств нет используемых здесь конструкторов. Они получены из настоящего анализа; readonly-свойствам ничего не присваивается. Не подменять их фиктивными Структура с похожими именами.
Учебные метки построены известным правилом по тому же Остаток. Разбор классификаций на обучающем источнике не доказывает обобщение на новых данных и не заменяет отдельную контрольную выборку. Для реальной закупки требуются реальные правила, данные и разрешение.
Количество элементов Классификации не равно автоматически КоличествоОбъектов. У одного элемента может быть несколько случаев; код проверяет сумму именно весов.
Корень может не иметь свойства условия по Остаток; это не разрешение придумать границу. ЗаполнитьЗначенияСвойств без явного списка копирует пересечение имен только в собственную структуру памяти. readonly-объект источника не меняется.
ЗначениеС/ЗначениеПо относятся к описанию интервала; не использовать их как готовое число класса и не угадывать включенность концов. Вероятность решения и процентная Ошибка результата — разные показатели; формат не меняет их математический смысл.
МаксимальнаяГлубина4 — настройка алгоритма, Уровень0 собственного обхода — счетчик программы. Точная структура дерева и соглашение о глубине требуют будущего реального исполнения, не обещаются по статическим тестам.
В этом уроке модель не получает новый ИсточникДанных и не выполняет прогноз. Ее тип и КорневыеУзлы привязаны к реальному созданию/обходу; остальные API модели должны изучаться отдельным полным прогнозным сценарием, а не чужими формальными target-привязками.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.