Решить задачу по комбинаторике с помощью Python

Цена договорная • безналичный расчёт, электронные деньги
01 марта 2019, 23:06 • 7 откликов • 99 просмотров
Есть товары и опции которые лежат на складах. Товар или опция может иметь фиксированное кол-во или быть бесконечной(вместо кол-ва указано None). При заказе можно скомбинировать один товар с несколькими опциями, соответственно нужно распределить заказанные товары с опциями по складам в заказы. Если товары в заказе можно отправить с нескольких складов, то нужно выбрать все их, если нельзя, то разбить на несколько заказов по складам.

Общая задача похожа на "Задача об упаковки в контейнеры" и "Задача раскроя". Единственное чтобы я выделил это то, что нужно комбинировать по складам, учитывая, что возможна отправка с двух складов. Также нужно учесть, что есть бесконечные товары и опции.

Для наглядности(синтаксис Python'a). ID опций, товаров, складов взяты наобум, можно вставить свои.

Товары - словарь со всеми имеющимися товарами, складами на которых он имеется и количеством(None - бесконечный) на этих складах {product_id: {warehouse_id: quantity}, ...}:
{1: {2: 7, 4: 3}, 13: {2: 7, 4: 3}, 21: {2: None, 4: None}}

Опции - аналогично {option_id: {warehouse_id: quantity}, ...}:
{3: {2: None, 4: None}, 10: {2: 10}, 9: {2: 10, 4: 10}, 8: {4: 2}}

Заказ - кол-во в данном случае определяет кол-во данного товара и кол-во каждой опции в данной комплектации, т.е. при количестве 2шт нужно взять 2шт товара и по 2шт каждой опции. Один и тот же товар с разными комбинациями опций рассматривается как отдельный:
[{'product_id': 1, 'quantity': 2, 'options': [3, 10, 9]}, {'product_id': 1, 'quantity': 1, 'options': [3, 9]}, {'product_id': 13, 'quantity': 5, 'options': [10, 9]}]

На выходе хотелось бы получить что-то такое. order_products - ключ из массива заказа.

При невозможности отправки с одного склада:
[{'warehouses': [4], 'order_products': [0, 1]}, {'warehouses': [2], 'order_products': [2, 3]}]

При возможности отправки с нескольких складов:
[{'warehouses': [2, 4], 'order_products': [0, 1, 2, 3]}]

При возможности отправки с нескольких складов и только с одного склада:
[{'warehouses': [2, 4], 'order_products': [0, 1]}, {'warehouses': [6], 'order_products': [3]}]

Товары в заказе(order_products) которых нет или не хватает на складе(учитывая опции) запихнуть в отдельный массив с максимальным кол-вом, например:
limit_exceeded = [{'order_product': 1, 'max_quantity': 2}, ...]

При желании использования библиотек - сообщить заранее.