
Подмести весь супермаркет Albert Heijn? Звучит несложно. Собственно, так и должно быть.
Но я студент-информатик, и у меня есть одна проблема — склонность оптимизировать процессы, которые, быть может, оптимизации не требуют.
Поэтому вместо того, чтобы просто делать свою работу, ну то есть… подметать… я поступил так, как поступил бы любой здравомыслящий человек: превратил план этажа супермаркета в решётчатый граф, создал визуальный редактор и написал на C++ оптимизатор пути, используя алгоритм имитации отжига (simulated annealing).
Но прежде, чем переходить к рассказу о том, как всё пошло наперекосяк, и как я осознал, что из-за таких вот вещей страдаем мы все, задам вам один вопрос:
Если бы вы на один день взялись делать мою работу (я бы не советовал, но чисто теоретически), и вам нужно было бы подмести весь этаж в Albert Heijin, какой бы маршрут вы выбрали — А или B?

Я серьёзно. Рассмотрите их. Какой вам кажется более эффективным для подметания пола в супермаркете?
Если вы выбрали А, мои поздравления — вы мыслите как алгоритм и наверняка являетесь роботом. (Удачи вам с решением капчи).
Но в техническом смысле вы правы. По расстоянию путь А короче, хотя по факту он совершенно бесполезен.
Только посмотрите на эти бесконечные повороты. Просто представьте себе, что вы бы вот так ходили, всё время поворачивая. Да вы бы казались безумцем и выглядели как заглючивший Roomba (робот-пылесос, — прим. пер.).
Путь А — это то, что случается, когда вы делаете оптимизацию не с тем акцентом.
В этом и будет заключаться мораль всей истории. Но мы к ней ещё придём, а пока я объясню, как всё происходило.
Шаг 1: превращаем реальность в простейшую модель
Сначала я взял план супермаркета и превратил его в сетку. Каждая клетка сетки либо пуста (требует подметания), либо является препятствием (стена, касса, брошенный кем-то на пол пакет йогурта).
Далее я создал визуальный редактор в Processing (инструмент на базе Java для тех, кто любит всё приукрашать), чтобы можно было легко спроецировать план этажа на сетку и экспортировать полученную схему.
В общем, сделать из имевшегося плана сетку оказалось весьма просто.

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

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


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

Теперь оставалось только перебрать полученную сетку с условием посещения всех узлов (клеток). Полученный результат и стал бы решением моей задачи.
(Иначе эта задача называется «Задача коммивояжёра». По ссылке можете прочесть о ней [англ.] подробнее и узнать, почему её так сложно решить).
Шаг 2: написание оптимизатора
Поскольку в графе такого размера найти лучший путь через вычисление не получится, нужно использовать эвристику. Вместо поиска идеального решения (которое вряд ли возможно) эвристический подход стремится найти очень хорошее.
В итоге я реализовал на C++ оптимизатор пути и в качестве алгоритма эвристики использовал имитацию отжига.
Если вам этот алгоритм не знаком, то его механизм основан на опробовании серии небольших изменений (также называемых локальными перемещениями)
Сначала алгоритм принимает каждое небольшое изменение (даже если оно ухудшает путь), но в процессе выполнения постепенно становится всё придирчивей и допускает только те изменения, которые путь строго улучшают.
Принцип работы этого метода отражает процесс остывания металлов при отжиге. Алгоритм начинает с «высокой температуры», чтобы опробовать множество возможных вариантов, после чего температура постепенно снижается, и он сходится к более стабильному состоянию, выбирая лучшее решение.

Посмотрите на эту гифку. Здесь видно, что процесс начинается весьма хаотично и постепенно сходится к стабильному решению. Так работает имитация отжига.
В качестве локального перемещения я использовал метод 2-opt. Его смысл таков: вы удаляете два ребра из проложенного пути и воссоединяете ранее связанные ими узлы другими рёбрами. Если это небольшое изменение улучшает путь, сохраняете. В противном случае либо всё равно сохраняете (если температура ещё высока), либо отбрасываете.

Потом просто делаете так миллиард раз. Вернее… ваш компьютер делает это миллиард раз.
Шаг 3: облом
Погоняв алгоритм какое-то время, я получил свой первый «оптимизированный» путь. Вот, что он мне предложил:

Только взгляните. Да у этого пути больше крутых поворотов, чем в фильме Кристофера Нолана. Ни один безумец не будет реально так подметать. Да вас в итоге стошнит, если даже попробовать.
Технически, он охватывает весь этаж. Технически, это (почти) кратчайший путь. Технически, он идеален.
Здесь есть удачные моменты, но в практическом смысле он абсолютно бесполезен.
Алгоритм сделал ровно то, что я просил (да и хорошо; страшно представить, если бы он сделал что-то совсем другое).
Просто я неправильно поставил задачу.
Шаг 4: оптимизируем под реальность
Я быстро понял, что оптимизировал не с тем акцентом. Расстояние — это не единственный важный момент.
Повороты тоже важны. Важен темп движения. Важно не выглядеть как глючный робот.
Поэтому я добавил в функцию затрат «штраф за повороты» и попросил алгоритм его минимизировать. По сути, я сказал ему: «Каждый поворот на 90° будет стоить тебе лишних баллов, а разворот на 180° — и того хуже».
В итоге маршруты стали более плавными, хотя расстояние чуть возросло.

Посмотрите. Вот так пройти уже реально. Такой маршрут можно поручить живому человеку и не бояться, что он тут же подаст заявление на увольнение.
Здесь мы оптимизируем уже не под расстояние, а под реальность.
Шаг 5: регулировка
А вот здесь начинается самое интересное.
Вы можете корректировать штраф за крутые повороты, используя это как своеобразный слайдер между «чистой эффективностью» и «реальной пользой».

И компромисс получается весьма наглядный. По мере увеличения штрафа маршрут становится плавнее, но и длиннее. Если же штраф уменьшается, то возрастает эффективность, а с ней и хаотичность.
Какой из маршрутов выбирать — решать вам. Всё зависит от того, насколько ловко вы можете поворачивать, насколько вам важно общее расстояние, и насколько устойчив ваш вестибулярный аппарат.
Шаг 6: горькая реальность
Но главная мораль истории всё же не в подметании полов.
Этот пример касается всего. К примеру, алгоритмы социальных сетей, оптимизированные на вовлечение пользователя. Они в этом реально хороши. И в чём же проблема?
Вовлечённость ≠ радость. Вовлечённость ≠ правда. Вовлечённость = клики, экранное время, помешательство и реактивность.
Какие последствия? Возмущение, распространение дезинформации, думскроллинг, тревожность.
Алгоритмы работают идеально и делают ровно то, для чего создавались. Ошибка лишь в функции затрат. (Разработчики Instagram вряд ли согласятся). Рекомендательные алгоритмы оптимизированы на увеличение времени просмотра и частоты кликов. Ваша бабушка может часами напролёт смотреть на YouTube сюжеты про теории заговоров.
Алгоритмы всё сломали. Бабушке от этого только хуже. И тут нечему удивляться.
Даже LLM вроде ChatGPT оптимизированы не на те показатели. Они ориентированы на то, чтобы звучать убедительно. Звучать так, будто они знают истинный ответ. И их задача не в том, чтобы быть правдивыми или честными.
Они обучены завершать шаблоны, а не отвечать «Я не знаю». Поэтому они просто гадают. Без малейшего стыда и грамматических ошибок. Причём всё это выходит за рамки техно-индустрии.
Вспомните о бизнесе. Большинство предприятий оптимизированы под наращивание прибыли. Наша планета, окружающая среда, мораль, этика? Все эти вещи не интегрированы в функцию затрат и в оптимизации не учитываются.
Использовал ли я этот оптимизированный путь в реальной работе?
Очевидно, нет. Я просто подметал пол, как обычный человек. Но процесс его поиска научил меня одной вещи, о которой я не забуду: нет никакого смысла в технической корректности, если вы решаете не ту задачу.
Вы можете писать идеальный код. Можете создавать безупречные системы. Можете заооптимизировать всё вусмерть с помощью функции затрат. Но на выходе всё равно может получиться отстой. Решающую роль играет не алгоритм оптимизации, а выяснение того, под какую метрику вообще нужно оптимизировать. Чаще всего мы даже не задаёмся этим вопросом. Мы просто оптимизируем процессы под то, что легко измерять, и надеемся, что сработает.
Спойлер: пожалуй, не сработает.
Если вы почерпнули из моих рассуждений что-то полезное, я рад. Если вам понравилось, как я чрезмерно усложнил простую задачу подметания пола, то и это здорово.
Так или иначе, спасибо за то, что прочли мой рассказ о попытке оптимизировать задачу, которая этого совсем не требовала.
Код моего оптимизатора доступен на GitHub.
Комментарии (47)

Vsevo10d
01.02.2026 09:12Мне кажется, пример автора нагляден, но не совсем верен по посылу изначально. Для уборщика не является чем-то плохим пройтись по уже почищенному. За счет пересечений его путь удлинится, положим, на 10%. При этом снижение скорости, вызванное поворотами, отнимет времени больше. Кроме того, если там и правда лежит плитка, то тем более нужно искать путь с максимально длинными прямыми, поскольку по плитке легче контролировать точность хода швабры.
Так что тут скорее дело не в том, что парадигма оптимизации ведет в тупик и не нужно алгоритмизировать то, что подвержено здравому смыслу. Нужно просто оптимизировать, исходя из правильных предпосылок, а эти правильные предпосылки не всегда очевидны. Нутк свести реальную задачу к правильной типовой – это и есть искусство прикладного математика.

randomsimplenumber
01.02.2026 09:12Нужно правильно выбрать цель оптимизации.

funca
01.02.2026 09:12Если автоматизировать бардак, то будет автоматизированный бардак - без разницы какова была цель.

venanen
01.02.2026 09:12Но только обычный бардак устранить не так просто, а имея детерминированную цифровую модель бардака, можно тысячу способов применить для того, чтобы бардак перестал быть бардаком.
P.S. «Бардак» в современном русском языке — это разговорное слово, означающее полный беспорядок, хаос, неразбериху или разруху в делах, мыслях, отношениях или помещении. То есть бардак не может быть автоматизирован, иначе он перестает быть бардаком, ведь автоматизировать можно только, что детерминировано и структурированно.

evkochurov
01.02.2026 09:12Вы рассуждаете о сферической автоматизации в вакууме. В реальном же мире все куда прозаичнее: после автоматизации бардака сопротивление попыткам навести порядок только вырастет - теперь упираться будет еще и система автоматизации.

Darkness_Paladin
01.02.2026 09:12Отличная иллюстрация народной мудрости: "Без нормального ТЗ -- результат ХЗ". Ну, или можно считать это проявлением диалектики.
Не прописал в условиях задачи, что движение по прямой предпочтительнее зигзагов -- вот и получил решение, где это условие не учтено )
Не прописал, что движение по прямой быстрее, чем затормозить-повернуть-ускориться -- опять же, не учтено.
Не прописал, что "ходьба по чистому" хоть и занимает время, но быстрее, чем рабочий ход -- и получил решение, где алгоритм тщательно избегает пересечений своего следа.

MEGA_Nexus
01.02.2026 09:12Использовал ли я этот оптимизированный путь в реальной работе? Очевидно, нет. Я просто подметал пол, как обычный человек. Но процесс его поиска научил меня одной вещи, о которой я не забуду: нет никакого смысла в технической корректности, если вы решаете не ту задачу.
По факту парень просто впустую потратил своё время и время читателей, которые читали его бесполезную статью.
Прочитав заголовок, я ожидал, что он устроился на ручную работу, а с помощью навыков её улучшил, т.е. использовал автоматизацию, а свободное время тратил на что-то полезное. Вот это было бы интересно почитать.
А так по факту парень просто потратил своё время впустую и по итогу сделал ошибочные выводы.
Зачем вообще использовать программирование, если ты всё равно будешь выполнять работу вручную? Может лучше купить с 1-ой зарплаты парочку роботов-пылесосов и настроить их под себя или создать свой робот пылесос, используя навыки программирования и Ардуино\малинку?
Пока роботы будут по ночам начищать полы в торговом центре, автор может заняться чем-то более интересным, например, готовиться к лекциям и зачётам в универе, программировать какой-нибудь SaaS сервис или даже просто торговать вещами на ebay\amazon, ведь знание программирования способно найти хорошие ниши с низкой конкуренцией и высокой маржой.
Замена ручного труда на механизацию - это прогресс. Замена механизации на автоматизацию - это прогресс. Добавить к автоматизации интеллект (чтобы убирало только там, где грязно) - это прогресс. Добавить к автоматизации автономность (чтобы само запускалось, когда нужно, а не ждало команды человека) - это прогресс. Создать алгоритм, чтобы автоматизация стала эффективнее - это прогресс.
Создать алгоритм, чтобы продолжать делать работу вручную - это пустая трата времени и своего таланта.

BorisBeast
01.02.2026 09:12Вы не поняли посыла. Это не "я все автоматизировал", а "я понял, что автоматизация автоматизации рознь".

lorc
01.02.2026 09:12Такое ощущение что мы с вами читали две разных статьи. Подметание пола - это просто фон. Знаете как в начале книги автор устанавливает контекст: "события разворачиваются на космической станции в 2075 году". Хотя, большинство историй можно рассказать используя другие декорации. Типа, если сменить старушку-процентщицу на крипто-барыгу, а Петербург - на Лондон, то в принципе ничего в "Преступлении и наказании" не изменится.
Так вот, статья не про полы. И даже не про оптимизацию движения на двухмерной карте. Это - всего лишь иллюстрации к главной, но довольно таки банальной мысли - "надо правильно выбирать критерий оптимизации". Точно такую же статью можно было написать про KPI, например. Как неправильно выбранный KPI все делает только хуже. Но обсуждение KPI уже всех задолбало, а тут - что-то новенькое.

Arisrarh_Pipetkin
01.02.2026 09:12Спасибо, было интересно, глубокая мысль в казалась бы алгоритмичном задании.

Superrad
01.02.2026 09:12А почему не стали делить на кластеры/сегменты убираемую площадь? Закрыл сегмент перешел к другому. Приоритизация / алгоритм уборки внутри сегмента могла дать прирост эффективности, экономии на времени, затратах итд.

useribs
01.02.2026 09:12Это ж перевод из счастливой Голландии (такие себе супермаркеты, почившая в бозе Billa организована лучше, в том числе и в РФ была)

wataru
01.02.2026 09:12Очень странный подход к задаче. Тут не надо строить решетчатый граф вообще. Вы же можете пройтись и подмести сразу коридор шириной и пол метра и метр и полтора. Вы двигаетесь непрерывно, а не дескретно шагами.
Соответственно, от плана вам нужна лишь топология помещений, Ребра оказываются коридорами и вам тут уже достаточно алгоритма Эйлерового цикла/пути, что на порядки проще и быстрее.

Jijiki
01.02.2026 09:12почему непрерывно, коридор ведь в метрической сетке. любое движение от точки А в Б происходит на делении хотябы по времени - получается тоже метрика, получается мы движемся свободно, но из-за того что стоим или нет, нога либо в воздухе либо нет, чтобы сделать шаг, пятка-стопа положение - фаза, да просто по шагам получается дискретность на метрическом разлинованом пространстве, причем сетка может иметь бесконечное уточнение до опр точности же
группа действий со шваброй, дискретно придётся останавливаться, мне почему-то кажется
надо сделать шаг, поставить совок сделать действие метлой убрать совок - в этот момент после шага задействованы руки, но во времени мы стоим на месте тоесть мы стоим в 1 точке, а потом переходим к следующей же, если взять изменение отрезка пройденого пути, тоесть факт движения, это дискретный момент

the_Silent
01.02.2026 09:12Наиболее ярко данная проблема, затронутая автором, проявляется в нынешнем обществе - когда вместо реальных ценностей всё подменяется такими суррогатами и прокси-метриками, как богатство, рост ВВП и "прогресс" (что бы это ни значило).

AuroraBorealis
01.02.2026 09:12ОтсыпьтеМожно мне немного реальных ценности? А то я как дурак все за фантиками бегаю. И да, я без сарказма.
FlyGst
01.02.2026 09:12Реальные ценности в том, чтобы что-то отдавать/создавать, а не только брать/потреблять.

the_Silent
01.02.2026 09:12Ценности первого порядка, которые могут (часто) не очень качественно заменяться ценностями второго порядка:
чистый воздух, вода, хорошее питание
защищенность от преступлений
здоровье
свободное время
и так далее. Принцип понятен, надеюсь?
Почему стремление максимизировать ВВП и доходы далеко не однозначно ведет к увеличению этих ценностей. К примеру, сверх меры зашибание копейки приводит к потере свободного времени, здоровья. Наличие кучи мигрантов для повышения ВВП и повышения прибыли ведет к росту преступности. Рост производства вызывает загрязнение воздуха и воды. Увеличение производства еды путем пичкания нитратами ухудшает качество овощей.
"Прогресс" это вообще отдельная тема. Как бы он за всё хорошее и против всего плохого, но имеет кучу последствий, включая истощение природных ресурсов, излишнюю трату ресурсов в гонке за производством каждый год всего "нового", запланированное устаревание, излишние вещи (как говорил Хрущев, "а у вас есть машинка, которая еду в рот сама заталкивает?").

SergDom
01.02.2026 09:12Любопытно, что в комментариях довольно много рекомендаций автору именно по технической стороне дела (применить такой алгоритм или сякой), оценок полезности решения или советов автору по жизни (которых автор, насколько я заметил, не просил).
И это отчётливо перекликается с 6 частью статьи:"нет никакого смысла в технической корректности, если вы решаете не ту задачу".
Вообще, похоже, именно эта часть, я бы назвал её философской, на мой взгляд ключевая в этой статье, и именно там автор сформулировал мысль, которую потом в нескольких вариациях повторили комментаторы, пеняя автору:
"Вы можете писать идеальный код. Можете создавать безупречные системы. Можете заооптимизировать всё вусмерть с помощью функции затрат. Но на выходе всё равно может получиться отстой. Решающую роль играет не алгоритм оптимизации, а выяснение того, под какую метрику вообще нужно оптимизировать. Чаще всего мы даже не задаёмся этим вопросом. Мы просто оптимизируем процессы под то, что легко измерять, и надеемся, что сработает. "
Ирония в том, что комментаторы, критикующие техническую сторону, сами того не заметив, подтверждают своими репликами правоту философских размышлений автора )

irod87
01.02.2026 09:12Отличная статья и отличный коммент!
Я давно заметил эту профдеформацию у себя и у остальных программеров - тягу все тотально оцифровать и автоматизировать, как будто втиснуть всю жизнь в цифру. Что-то сродни "Когда у тебя в руках молоток, все задачи кажутся гвоздями".
Это очень вредная заморочка. Мало того что жизнь сильно теряет краски если оцифровать ее какие-то важные части (это как будто вы решаете использовать например только глаза, и отказываетесь от остальных органов чувств), так еще из-за этого распыления остается мало сил на действительно нужную автоматизацию. Короче для себя я понял что чтобы быть по-настоящему хорошим айтишником, надо по-чаще из айти "выходить" в физический мир.

danial72
01.02.2026 09:12Много пафоса, мало логоса.
Автор задачи решает не ту задачу, потому-что неправильно подошел к анализу задачи.
Ситуация: автор подметает пол. Но не указано чем, как, какой ширины коридор, какая ширина инструмента.
Исходя из этих данных, можно было бы строить графы и оптимизации. Скорее всего, алгоритмтическая оптимизация и не потребовалась бы вовсе, если бы он попросил инструмент пошире, чтобы за один проход зигзагообразным движением очистить всю ширину.

shornikov
01.02.2026 09:12Меняем чувака на робота - и вот уже вариант А - хорош, ибо экономит электричество*.
*Скорее всего нет, и время - тоже. Но робота хоть не тошнит.

Smartor
01.02.2026 09:12Как всегда - программа посчитала то, что ей приказали, а не то, что хотел автор:)

foxweb
01.02.2026 09:12У меня в универе был курс теории графов — максимально душный, унылый и непонятный предмет. Ах, если бы нам объясняли тему на подобных примерах и давали бы подобные задачи и курсовые работы с решением через визуализацию — было бы намного интереснее и нагляднее.

peacemakerv
01.02.2026 09:12На картинкахВ алгоритме не хватает функции "долбануть шваброй того, кто грязными ножищами по мытому".

serg_egor
01.02.2026 09:12Вот она наглядно беда: бездумное программирование ради программирования.
Автоматизация не есть процесс переноса математически обоснованного решения на практику.
Автоматизация которая нужна это:
1) Берём лучшую уборщицу; 2) отцифровываем все её действия - как, в каких случаях, в каких местах она делается то-то и то-то; 3) прогоняем подобное на нескольких топовых уборщицах, сверяем и дополняем результат; 4) описываем то, что насчитали в алгоритм.
Так сделали токарный станок, так делали и делают промышленную автоматизацию. Декомпозиция работы спецов до шага, перенос этого шага в автомат.
По поводу выводов: вовлечённость не равно счастье. Так а почему оно должно быть равно?) потому что так думает пользователь?)
Бабушку/детей/ родителей жалко, согласен. Она не вывозит всего того, что на неё навалила индустрия. Бабушке нужна помощь её детей/внуков, так же, как нам нужна была её помощь в детстве.
MasterMentor
И не говорите после этого, что навык ИТшника не пригодится после учёбы в реальном мире! Плюсом будет и то, что на рынке труда уборщиц, он даёт конкурентные преимущества!
ahabreader
Но это не точно.
Jijiki
навык программирования позволяет писать на визуал бейсике, и делать умный шаблон из пачки картинок - проверено ), тоесть многократное повторение рутины может привести к поиску решения повторения ручного