Алгоритм наявності та розміщення номерів у готелі @ MMT

У MakeMyTrip ми обслуговуємо різноманітний набір покупців готелів та допомагаємо їм складати плани, враховуючи їх різноманітну мету подорожі, заповнення та інформацію. При цьому, дві найважливіші потреби користувачів, які повинні бути задоволені для всіх, однакові - наявність готелю та ціна номера відповідно до бюджету. У цьому дописі в блозі ми ділимося деякими уявленнями про те, як ми збільшили загальну доступність готелів на нашій платформі та використовували динамічне програмування для вирішення проблеми пошуку "найдешевшої комбінації номерів", щоб зробити пропозицію більш потужною та корисною для наших клієнтів.

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

Наявність готелів: Найважливіше показати клієнту достатньо готелів на вибір на сторінці списку готелів. Нульова або низька доступність готелів призводить до того, що на самій сторінці лістингу потрапляє чимало клієнтів, що призводить до потенційного збитку для бізнесу.

Ціна номеру: Більшість мандрівників порівнюють ціни на номер в готелі через Інтернет-туристичні агенції (OTA) та роблять операцію на OTA, пропонуючи найнижчу ціну. Зважаючи на те, що значна кількість замовлень відбувається в номерах з найдешевшою ціною, важливо показати / виділити найдешевшу ціну на номері на сторінці деталей готелю, щоб допомогти клієнту швидко прийняти рішення.

Низька доступність готелю

Виявлення проблеми

У MakeMyTrip ми реєструємо безліч даних і регулярно їх аналізуємо, щоб дійти до поважних даних. Одним з наших останніх висновків була низька або нульова наявність готелів на сторінці списку готелів для значної кількості пошукових запитів у місті. Для цього були насамперед дві причини:

  • Менше запасів у піковий сезон / довгі вихідні
  • Відсутні тарифи в системі інвентаризації MakeMyTrip для потрібної кількості (наприклад, готель не налаштував тарифи для 3 дорослих)

Візьмемо приклад, щоб краще зрозуміти це. Нижче наводиться короткий опис інвентарю, завантаженого готелем в нашій системі для готелю "X" (А для дорослих та C для дитини).

Рис (1): Знімок інвентаризації

Пошук користувачів 1 (2 кімнати: кімната 1–1А, кімната 2–1А) - У цьому випадку, хоча у нас є 3 (хоча різні типи) номерів, ми повертали нульову кількість готелів, оскільки ми відповідали критеріям пошуку для кожного тип кімнати та жоден тип приміщення не мали кількість інвентарю ≥2.

Пошук користувачів 2 (Кімната 1–3А) - І в цьому випадку ми повертали нульову кількість готелів, оскільки готель не встановив тарифи за вищезазначеними критеріями пошуку.

В обох випадках існував спосіб виконати критерії пошуку користувачів, комбінуючи кімнати різного типу. Проблема стає набагато складнішою, оскільки кожен готель має свій поріг віку дитини та відповідні ціни.

Триточне рішення

  1. Змінення критеріїв пошуку - ми зупинили відповідність точним критеріям пошуку користувачів відповідно до кожного типу номерів і почали пошук із трансформованим запитом пошуку. Це особливо робиться для пошуків із більшою зайнятістю, якщо доступність загалом є низькою.
  2. Побудувати алгоритм комбінації найдешевших кімнат - Для наших клієнтів найдешевша угода - найкраща. Щоб вирішити це та проблему доступності готелів, було доцільно побудувати алгоритм, щоб представити користувачам найдешевші комбінації номерів.
  3. Попросіть готельєрів налаштувати ціни для вищої заповненості - Оскільки 60% користувачів подорожують соло або як пара, готельєри, як правило, оптимізують тарифи та інвентар для одномісної та подвійної розміщеності. Щоб допомогти клієнтам отримати кращі результати пошуку для заповнення> 2, ми попросили готельєрів налаштувати всі можливі комбінації вмісту, які вони підтримують.

Ось як ми думали, що загальне рішення має працювати.

Рис. (2): Діаграма

(1) та (2) виділені зеленим кольором. Залежно від каналу, яким користується готель, ми можемо мати або не мати необхідної інформації для запуску найдешевшого алгоритму комбінування номерів. Для обробки таких випадків ми побудували кілька додаткових алгоритмів для генерування / прогнозування необхідних даних (кількість запасів є одним з них).

Вплив на бізнес

Ми реалізували і (1), і (2). Як і очікувалося, кількість номерів на готелі зросла в багато разів на нашій сторінці переліку запитів на пошук більш ніж 2 дорослих. Ми також почали отримувати додаткові ночі на 5% щодня. Загалом, кількість бронювань, що мали більше 2 дорослих, на 50% більше.

Фіг. (3): Тенденція бронювання до та після виходу функції

Обчислювальні виклики та підхід

Проблема з найдешевшими рекомендаціями щодо номерів - це проблема комбінаторної оптимізації.

З огляду на N готельних номерів та P (дорослих + дитина) гостей, знайдіть найдешевші комбінації номерів для розміщення гостей P.

Щоб запустити будь-який алгоритм оптимізації, нам потрібно було отримати атрибути даних, необхідні для:

  • Створіть усі можливі місця для приміщення
  • Розрахуйте ціну для таких випадків

Для цього ми почали використовувати атрибути рівня готелю та номерів, такі як віковий поріг дитини, максимум дорослих / дітей, дозволених в номері, кількість доступних номерів для кожного типу номерів, додаткова ціна для дорослих і т.д. до якого він не стягуватиме додаткову оплату (базове розміщення), до якого віку він вважатиме гостя дитиною, ціна додаткової дитини, ціна додаткового дорослого, максимум дорослих / дітей, які можуть розміститися у кожній кімнаті. Про все це потрібно подбати, створюючи та розраховуючи ціну кожної кімнати та розміщення. Поводження з цими атрибутами збільшило обчислювальну складність у багато разів. Додатковим завданням було збереження непорушних строків пошуку. Ці обчислення слід проводити в режимі реального часу та за запитом, що містять 200-250 готелів.

Хоча ми завжди мали на увазі динамічне програмування для вирішення цієї проблеми, ми розглядали грубе рішення та кілька жадібних підходів, щоб дізнатись, чи достатньо вони / працювали для наших випадків використання.

Brute Force Solution: Це передбачало створення всіх можливих комбінацій для даної інвентаризації з усіма тарифними планами. Тоді ці кімнати також повинні бути обкладені клубами з різними комбінаціями розміщення. Це зумовило експоненціальну часову складність.

Фіг.4 (4): Підхід грубої сили призводить до експоненціальної часової складності

Це було можливо, але не масштабується. Також додасть значну затримку пошуку api.

Жадібні підходи: ми вивчили кілька стратегій, але знайшли зустрічну справу у кожній з них. Основна проблема полягала в тому, що у нас немає номерів, відсортованих за ціною та кількістю відвідувачів. Більше того, будь-яка покращена кімната / люкс може вмістити більше людей порівняно зі стандартною кімнатою.

Найдешевший комбінований алгоритм

Давайте зрозуміємо кілька термінів і позначень, перш ніж перейти до алгоритму.

Рис. (5): Термінологія для найдешевшого комбінованого алгоритму

Ми змоделювали проблему пошуку найдешевшого поєднання кімнат навколо дуже відомої проблеми 0–1 рюкзака. Елементи (N) та ваги (W) в проблемі рюкзака вільно відображають набір фізичних номерів у готелі та різні можливі комбінації розміщення (починаючи з 0 і ведучи до потрібної кількості). Однак у нашому випадку були деякі унікальні обмеження, які потребували особливого поводження.

  1. Підпункти / Віртуальні кімнати: кожен предмет унікальний у проблемі з рюкзаком 0–1, але це не так у нашому випадку. Фізичну кімнату (предмет) необхідно враховувати з усіма можливими розміщеннями та тарифами, щоб забезпечити унікальність у наборі предметів. Це призводить до створення віртуальних кімнат для кожної фізичної кімнати. N в задачі 0–1 з рюкзаком насправді відображає набір віртуальних кімнат у нашому випадку.
  2. Забезпечення фізичного приміщення використовується один раз: Це прямий підсумок (1). Хоча ми використовуємо віртуальні кімнати для всіх розрахунків та рішень в алгоритмі, необхідно забезпечити, щоб фізична кімната використовувалася лише один раз для кожної комбінації кімнат, і потрібно знайти найкраще чергування у випадку будь-якого конфлікту.
  3. Корпусні кромки під час заповнення залишкової зайнятості: нам довелося опрацювати кілька крайніх випадків, посилаючись на вже вирішені підпроблеми. наприклад багато готелів не дозволяють бронювати номер із дітьми. Нам також потрібно розглянути випадки, коли ми виконали повноліття дорослого за допомогою віртуальної кімнати і залишилося лише розміщення дітей.

Основні кроки для побудови алгоритму

  1. Отримайте результат перетвореного пошукового запиту.
  2. Створіть двовимірну матрицю T із усіма можливими розміщеннями кімнат у вигляді стовпців (W) та віртуальних кімнат у вигляді рядків (N).
  3. У кожній комірці двовимірної матриці ми розглядаємо дві можливості - вибрати відповідну віртуальну кімнату як частину оптимального рішення або відкинути її. Ми розраховуємо вартість, пов’язану з віртуальною кімнатою і без неї, і вибираємо найдешевший. Кожна комірка матриці зберігає ключові атрибути кімнат, які використовуються для заповнення зайнятості цієї комірки.

Матриця заповнюється способом знизу вгору з використанням нижнього відношення:

Фіг. (6): Формула обчислень

4. Поверніть результат після проходження матриці.

Приклад:

Рис. (7): Деталі щодо номеру / тарифу

Для вищевказаних вхідних параметрів буде створена наступна двовимірна матриця. Помаранчевий стовпець відображає ціну, що відповідає кожній віртуальній кімнаті відповідно до конфігурацій готелю.

Рис. (8): 2D-матриця, що показує записи для 3 дорослих та 2 дітей. Недійсні записи позначені як

Осередки, виділені зеленим кольором, показують найдешевше поєднання номерів за заданими критеріями пошуку. Ідентифікатори номерів, згадані в комірці, описують, які кімнати слід розглядати, а їхні підписники визначають розміщення кожної кімнати. Клітини, виділені синім кольором, - це ті, які використовуються для обчислення зеленої клітини рекурсивно (використовуючи згадане вище відношення рецидивів).

Цей алгоритм спрацював досить добре у виробництві, не впливаючи на затримку 99-го відсотка нашого API пошуку. Навіть після кешування цих результатів рекомендацій ми все ще обробляємо близько 15 тис. Унікальних комбінацій готелів щохвилини.

Особлива подяка Аджай Сінгху та Абхієет Шараду за допомогу в розробці цього блогу.