Определение порядка расчета связанных формул




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

39 Comments

  1. mszsuz

    Стало интересно 🙂 Можно и проигнорировать порядок:

    Т = Новый Структура;
    Т.Вставить(«Б», «Вычислить(Т.А) + 1»);
    Т.Вставить(«Ц», «Вычислить(Т.А) + Вычислить(Т.Ф)»);
    Т.Вставить(«Д», «Вычислить(Т.А) * Вычислить(Т.Ц) + Вычислить(Т.Е)»);
    Т.Вставить(«Г», «Вычислить(Т.Б) + Вычислить(Т.Д)»);
    Т.Вставить(«А», 1);
    Т.Вставить(«Е», 2);
    Т.Вставить(«Ф», 3);
    Сообщить(Вычислить(Т.Г));
    

    Показать

    Reply
  2. mickey.1cx

    (1) mszsuz, идея интересная, спасибо.

    Только в вашем примере происходит расчет для одной конечной точки.

    В контексте моей задачи, при изменении одной ячейки количество конечных точек заранее неизвестно.

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

    Reply
  3. ИНТЕГРА

    Ндаааа…. ты долго писал это чудо? Про рекурсию не слышал? (сейчас полезут оппоненты из другой ветки, там меня шапками чуть не закидали — рекурсию обсуждали)

    Reply
  4. mickey.1cx

    (3) ИНТЕГРА,

    Шапок мешок несу.

    Зайду к соседу, скажу

    Про рекурсию.

    Может более предметно попробуешь, а то вроде бы и сказал, а как-то объемно очень получилось, в пространство.

    Reply
  5. ИНТЕГРА

    (4) во-первых не стоило изобретать свой синтаксис. В данной задаче это не оправдано и слишком накладно. Зачем?

    Во-вторых (следуя из п.1) вычислять каждую ячейку тебе надо командой: «Вычислить(<ТекстЯчейки>)».

    Ну и в-третьих — у тебя должна в контексте выражения п.2 быть определена функция а-ля «ВычислитьЯчейку(<АдресОбласти>)». Она должна рекурсивно вызвать саму-себя (тебе для этого даже делать по-моему ничего не надо).

    В результате тебе надо просто удалить 95% твоего кода, а вместо него продумать заглушку — чтоб рекурсия не зацикливалась — это очень просто.

    Reply
  6. mickey.1cx

    (5) ИНТЕГРА, ок, спасибо.

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

    Свой синтаксис необходим. Реальные формулы расчета изначально зашиты в шаблон и имеют вид:

    СуммаРаздела([ПланПродаж]), ИтогСтроки([ПланПродаж]), {КоэффициентРоста} * [ПланПродаж], ([ФактПродажиНал] + [ФактПродажиБезнал]) / [ПланПродаж] и другие интересные варианты.

    Соответственно, мне нужно как то выделять независимые параметры, параметры значений 1С.

    После получения данных заполнения происходит привязка параметров 1С к идентификаторам (например ПланПродаж_c4e33f6c-26ba-4979-aa32-36dd798db4d2) , формирование окончательного набора формул на основе шаблона, выполняется процедура именования необходимых ячеек табличного документа.

    По поводу рекурсии. Сейчас расчет ячеек происходит в цикле

    Для Каждого ВершинаПорядка Из ПорядокРасчета Цикл

    Можно конечно код цикла обернуть в рекурсию, брать первый элемент списка с последующим его удалением и проверкой на количество элементов списка при каждой итерации. Но зачем?

    Reply
  7. ИНТЕГРА

    (6)

    Можно конечно код цикла обернуть в рекурсию

    Конечно-же не об этом речь. Во-первых тебе на надо будет делать парсинг твоих выражений, а этот цикл вообще не понадобится.

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

    Reply
  8. mickey.1cx

    (7) ИНТЕГРА,

    Любые функции доступны, если правильно подготовить формулу. Смотри функцию ВычислитьРезультат

    Выполнить(«Результат = » + Формула)

    Такие конструкции без проблем отработают:

    Формулы.Вставить(«c», «Мин([a],[f])»);

    Либо

    Формулы.Вставить(«c», «МояСуперФункция([a],[f])»);

    Проверено.

    Reply
  9. mickey.1cx

    (7) ИНТЕГРА, по поводу рекурсивного вычисления,

    оно имеет смысл для обхода деревьев

    в случае рекурсивного обхода графа вершина 5 будет рассчитана два раза

    При изменении вершины 2 нет смысла рекурсивного обхода вершины 4 к вершине 6, пока не будет рассчитана вершина 5

    Может быть и такое

    Reply
  10. ИНТЕГРА

    (9) очень плохо, что ты сам увидел как это реализовать через рекурсию. Достаточно добавить проверку: если ячейка уже расчитывалась ранее — брать ее значение сразу. Графом я как раз не представляю как решить такую задачу. От может ты в ответ меня просветишь.

    Кстати лет 10 наверно назад писал обработку для 1С77, которая выгружает в текстовый документ данные из базы. Затем этой-же обработкой можно было загрузить в идентичную конфигурацию эти данные. Работала она с любыми метаданными, код был около 500 строк. Структура базы 1С сам понимаешь — гораздо сложнее твоих примеров. Я ее продавал даже по интернету, тогда инфостарта вроде небыло, через проклаб.ру торговля шла, по 300р за шт 🙂

    Reply
  11. mickey.1cx

    (10) ИНТЕГРА, фишка как раз в том, что при рекурсивном расчете ячейку необходимо пересчитывать каждый раз,

    поскольку только при последнем обходе все вышестоящие ячейки будут рассчитаны корректно.

    Попробуй рекурсивно обойти второй рисунок. При левом проходе 1-2-5 вершина 5 получит еще не рассчитанное значение вершины 3, поскольку

    эта вершина будет обрабатываться, после окончания обхода левой ветки.

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

    Для этого как раз в формуле через [ ] выделяются вершины графа, по которым строятся списки смежности ячеек.

    При обработке изменения ячеек на основе этих списков происходит построение порядка расчета.

    В начале статьи я писал, что порядок расчета на реальной разработке достигал 260 элементов, общее количество формул около 1000, в зависимости от настроек.

    На таком графе рекурсивный обход будет явно не самой быстрой операцией.

    Теорию для обхода графа брал здесь, поиск в ширину.

    Reply
  12. minimajack

    (11) давайте начнем исходить из задачи…

    возьмем два варианта решения

    1. Автора

    2. Рекурсивный

    И проверим где быстрее будет решение.

    Reply
  13. ИНТЕГРА

    (11) я-же тебе писал — у меня база выгружалась. Там логика гораздо запутанней, чем у тебя. и «Формулы» с вложенностью более 100 уровней достигали. Мне кажется рекурсия для таких задач проще в реализации, ни в коем случае не утверждаю что твой способ плох (для этого надо изучать тему, а мне лень 🙂 ). Просто предлагаю альтернативный вариант реализации. Если тебе интересна эта тема — попробуй на нем реализовать, увидишь, что кода станет в разы меньше. За пару часов можно набросать рабочий алгоритм. Вопрос универсальности: а сможет твой алгоритм обхода графа выгрузить БД в текстовый файл?

    (12) Скорость на задачах автора вряд ли будет отличаться, а вот кода, значительно больше у него.

    Reply
  14. minimajack

    утрировано, такое посчитает?

    Формулы.Вставить(«с», «5»);
    Формулы.Вставить(«a», » если [k] тогда [с] иначе [b]-1 «);
    Формулы.Вставить(«b», » если [k] тогда [a] иначе [с] «);
    
    Reply
  15. mickey.1cx

    (12) minimajack, можно конечно проверить и на практике.

    А можно использовать такую штуку, как О-нотация оценки сложности алгоритмов.

    Исходя из этой теории, алгоритм формирования порядка очереди расчета с последующим обходом

    будет иметь сложность О(N log N) + О(N), в то время как рекурсивный обход, как минимум O(2#k8SjZc9DxkN)

    На графике явно видно. как будет расти количество операций при увеличении количества элементов.

    Reply
  16. mickey.1cx

    (14) minimajack,

    допустим, Формулы.Вставить(«a», «?([k], [с], [b]-1)»);

    Reply
  17. mickey.1cx
  18. ИНТЕГРА

    (14) minimajack, в рекурсии надо делать дополнительную проверку от циклических ссылок (причем только при сочетании условий). Интересно как графы на это отреагируют.

    Reply
  19. mickey.1cx

    (13) ИНТЕГРА, ок, постараюсь подвести итоги 🙂 Каждый алгоритм хорош, там где хорош.

    В моей задаче оптимален как раз обход графа в ширину.

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

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

    в контексте данной задачи даже не рассматривается. Соответственно, «избыточность» кода

    приемлема, поскольку в моем случае это будет работать быстрее. Это не мое заявление,

    существуют математические методы оценки скорости и сложности алгоритмов.

    По поводу выгрузки, теоретически можно и реализовать. Только вот здесь как раз использовать граф смысла нет,

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

    рекурсивно обойти, пропуская обработанные ссылки.

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

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

    такое в Excel — ругнется.

    Reply
  20. ИНТЕГРА

    (19)

    смоделировать обход классической

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

    в контексте данной задачи даже не рассматривается

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

    Если таковая появляется, то это означает ошибку в логической структуре формул

    Как твой алгоритм отреагирует на такую «ошибку»?

    Reply
  21. minimajack

    (16) я привел псевдо цикличность…она вроде есть, но ее как бы нет.

    то есть [а] зависит от [б],[с],[к]; но и [б] зависит от [а],[с],[к].

    Reply
  22. mickey.1cx
    Reply
  23. minimajack

    (22) хорошо…почему вы указали формулу:

    в то время как рекурсивный обход, как минимум O(2#k8SjZc9DxkN)

    это же неправда.

    Reply
  24. mickey.1cx

    (20) ИНТЕГРА,

    Допустим, есть функция f(), использующая рекурсивный вызов самой себя по спискам смежности вершин.

    Рассмотрим работу этой функции на простом примере.



    При вызове f(1) вызываются последовательно f(2) и f(3).

    Для f(2), соответственно, f(4) и f(5), для f(3) — f(5) и f(6).

    Пожалуйста, рекурсивно мы зашли в вершину 5 два раза, ничего не зависло, все ок.

    Я к тому, что подобный подход не оптимален. Например, в конечной точке могут консолидироваться входные значения

    с последующей записью в регистр.

    Понять, видимо, хочу. Поэтому и потрудился рассмотреть вариант с рекурсией. Более того,

    привел аргументы в пользу ее неоптимальности в текущем контексте.

    На чем же основаны твои выводы, мне непонятно. Извини, не телепат.

    Как твой алгоритм отреагирует на такую «ошибку»?

    Так же, как и рекурсия в подобной ситуации, зависнет. В контексте задачи наличие циклов в графе не учитывается,

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

    соответствующие алгоритмы (например, на основании поиска в глубину) уже разработаны.

    Reply
  25. herfis

    Просто ИНТЕГРА овладел молотком, и теперь все задачи вокруг него ему кажутся гвоздями 🙂

    Зачем нужна отвертка, если шуруп можно вбить молотком и не совершать кучу сложных вращательных движений?

    К чему все эти сложности, другие инструменты и техники, если есть простое, элегантное и универсальное решение?

    Не так крепко держаться будет? Подумаешь! Для современных стенок и полок вполне нормально, говорит ИНТЕГРА. И доля правды в его словах есть. Ведь вбить шуруп в самом деле намного легче и естественней, чем вкрутить гвоздь. И даже будет держать. Вполне себе универсально и просто.

    ЗЫ. Извиняюсь за яд, просто в недавнем обсуждении он настаивал на рекурсивном решении для обхода дерева ссылок в БАЗЕ ДАННЫХ через точку, вместо порционного их доставания запросами сразу по нескольку уровней за раз, приводя похожие доводы. Мол раз дерево — значит тупой рекурсией и надо обходить, как завещано. И всё тут. Хоть кол на голове теши. Код мол получается простой и элегантный, а всё остальное — от лукавого. Оценкой сложности алгоритмов его не пронять. Отсутствующие знания он отметает как несущественные. Задача программистов, говорит он — писать простой и элегантный код. Оптимизация производительности, мол, должна происходить на более низких уровнях. И частично он опять-таки прав. Функциональные языки во многом такую оптимизацию и делают. А какие-нить мудрые фрейморки могли бы и на БД делать (или делают) нужную оптимизацию. Но, блин! Нельзя же закрывать глаза на реальную производительность реальных решений! И уж тем более — на разные порядки роста сложности!

    Reply
  26. herfis

    Обход графа в ширину просто плохо ложится на рекурсию, т.к. используется очередь а не стек. Другими словами, рекурсия для этого — неподходящий инструмент.

    А вот обход графа в глубину должен отлично лечь на рекурсию (безотносительно сабжевой задачи).

    Reply
  27. minimajack

    (24) количество узлов 6, в вершину 5 зашли два раза итого рассчитали 7 узлов…а никак не минимум 2#k8SjZc9Dxk6…вот максимум 2#k8SjZc9DxkM — да это возможно

    Reply
  28. mickey.1cx

    (23) minimajack,

    пятница, наверное 🙂

    на свежую голову, от О(N log N) до O(N#k8SjZc9Dxk2)



    при движении из вершины 1, поиск в ширину — 6 вершин, рекурсия — 9

    (24) опередил ))

    Reply
  29. minimajack

    (28)

    проверил на рекурсии — приблизительно такой порядок времени

    1600 переменных

    матрица 40х40 — формул 1600

    связь вида по строкам = значение левой ячейки + номер строки + значение ячейки слева вверху

    изменение первой ячейки приводит к перерасчету 800 связанных формул — и занимает это все 3 секунды…уровень глубины ~600

    связь вида по строкам = значение левой ячейки + номер строки + значение ячейки вверху — это намного тяжелее

    матрица 40х40 — изменение первой ячейки приводит к перерасчету 1 560 переменных — и занимает это все 8 секунд…уровень глубины ~1560

    матрица 70х18 — изменение первой ячейки приводит к перерасчету 1 190 переменных — и занимает это все 6,3 секунд…уровень глубины ~1190

    матрица 14х20 — изменение первой ячейки приводит к перерасчету 260 переменных — и занимает это все 0,63 секунд…уровень глубины ~260

    Reply
  30. ИНТЕГРА

    (24) ну что за ерунда! Мыслишь однобоко: «Если рекурсия, значит она так-то и так-то будет работать!» — это твое представление о ней. Нет! Она будет работать так как ты ее реализуешь. Моя рекурсия при двойном вхождении не зависает: т.к. при первом входе производится расчет и запоминается значение для этой ячейки, при повторном обращении — сразу возвращается значение (наверно и ты смог бы в графе эту ситуацию аналогично решить, но видимо не получается, либо просто не догадался)

    Reply
  31. ИНТЕГРА

    (29) minimajack, Теперь осталось с графом такой анализ провести и сравнить 🙂 У ТС формул меньше изначально и за эти секунды пользователь ничего не потеряет я думаю.

    Reply
  32. ИНТЕГРА

    (25) herfis, (26) ну ты философ 🙂

    К чему все эти сложности, другие инструменты и техники, если есть простое, элегантное и универсальное решение?

    Ну нет в графе такой универсальности как в рекурсии. Язык 1С всяко универсальней, чем а-ля [ИмяОбласти] — в чем элегантность?

    Тоже самое хотелось-бы сказать о разработчиках ЗУП. Произвольные алгоритмы в видах расчетов программируются безобразно — могли просто делать вызов «Вычислить()».

    Reply
  33. mickey.1cx

    (29) minimajack, наконец то дошли руки проверить на действующей разработке, количество вершин 1356, формул 1092.

    Тест по три замера на самом длинном участке.

    Граф:

    Итераций, очередь 413

    Итераций, порядок 205

    Время, мс 132

    Итераций, очередь 413

    Итераций, порядок 205

    Время, мс 128

    Итераций, очередь 413

    Итераций, порядок 205

    Время, мс 234

    Рекурсия:

    Итераций, порядок 2 912

    Время, мс 2 471

    Итераций, порядок 2 912

    Время, мс 2 500

    Итераций, порядок 2 912

    Время, мс 2 042

    Reply
  34. minimajack

    (33) рекурсия-рекурсии рознь. У меня после некоторых оптимизаций количество операций(расчетов) в рекурсии стало таким же как и в графе…

    Reply
  35. mickey.1cx

    (34) minimajack, я это прекрасно понимаю, все зависит от конкретной задачи.

    Например, если предполагается обход структуры, подобной дереву значений, то рекурсия здесь предпочтительна.

    Хотя бы потому, что: 1) не надо предварительно строить связи этих данных, а приступить сразу к обходу;

    2) смысла определения порядка расчета тоже нет, входными параметрами текущего расчета будут являться

    только значения предыдущей итерации.

    В моем же случае мы имеем множество связей одной вершины с вершинами из соседних веток.

    Соответственно, при увеличении количества вершин растет количество связей.

    При 1356 вершинах моего графа количество связей составило 3625, отсюда и такая разница по времени выполнения.

    Визуализацию графа прилагаю.

    Reply
  36. minimajack

    (35) еще раз повторюсь

    важно: не количество формул, не количество вершин…а форма графа.

    Вот пример генерации графа:

     Для k=1 По 20 Цикл
    Для n=1 По 20 Цикл
    Если k=1 Тогда
    ЗначениеФормулы = «=» + n;
    Иначе
    ЗначениеФормулы = «=» + n + » + [«»R» + Строка(n) + «C» + Строка(k-1) + «»»]»;
    Если n > 1 Тогда
    ЗначениеФормулы = ЗначениеФормулы + » + [«»R» + Строка(n-1) + «C» + Строка(k) + «»»]»;
    КонецЕсли;
    КонецЕсли;
    КонецЦикла;
    КонецЦикла;
    

    Показать

    элементарная сетка — по факту ужасный вариант для рекурсии…

    [10×10] 100 мс — в среднем затрачивается на перерасчет при изменении ячейки C1R1

    [20×10] 260 мс — в среднем затрачивается на перерасчет при изменении ячейки C1R1

    [20×20] 700 мс — в среднем затрачивается на перерасчет при изменении ячейки C1R1

    [50×50] 9800 мс — в среднем затрачивается на перерасчет при изменении ячейки C1R1

    [100×100] 80000 мс — в среднем затрачивается на перерасчет при изменении ячейки C1R1

    Визуализация [20×20]:



    Аппроксимация:

    Reply
  37. mickey.1cx

    (36) minimajack, спасибо за проделанную работу.

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

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

    Для обычного дерева количество связей всегда будет равно n-1, сложность (n-1)/n -> 1

    Сетка 10х10 — 180, 20х20 — 760, 30х30 — 1740, для n#k8SjZc9Dxk2 = 2*(n#k8SjZc9Dxk2 — n), сложность 2*(n#k8SjZc9Dxk2 — n) / n#k8SjZc9Dxk2 = 2(1 — 1/n) -> 2

    Сложность формы моего получается 3625 / 1356 = 2,67.

    Reply
  38. minimajack

    (37)

    после дополнительных модификаций сложность(временную) рекурсии удалось снизить еще на 12%…

    [10×10] 85 мс

    [20×10] 241 мс

    [20×20] 608 мс

    [50×50] 8800 мс

    [100×100] 70000 мс

    вы можете привести результаты ваших испытаний, вашим алгоритмом и таки доказать что он быстрее?

    Меня интересуют накладные расходы…

    Reply
  39. ИНТЕГРА

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

    Пример моей реализации тут: http://infostart.ru/public/511773/

    Reply

Leave a Comment

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