Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Разделить количество бананов в упаковке по корзинам - buckets (SQL?) / 25 сообщений из 30, страница 1 из 2
20.06.2019, 16:23
    #39828867
watson
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
Условие:
Есть некое количество бананов, расфасованных по нескольким упаковкам.
В каждой упаковке разное количество бананов.

Задача:
Равномерно разложить бананы в упаковках по корзинам.
Делить упаковку нельзя.

Пример:
упаковка 1 - 10 бананов;
упаковка 2 - 3 банана;
упаковка 3 - 2 банана;
упаковка 4 - 1 банан.

2 корзины.

Должно получиться - корзина1 (упаковка 1), корзина2 (упаковка 2, упаковка 3, упаковка 4).

Хочется найти решение на SQL.
Напрашивается ntile() по бананам, но не понимаю как привязать условие с неделением упаковки.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
with c
as
(
    select rownum id, t.*
    from
    (
    select 'pack_1' pack, 'banana_1' banana from dual
    union
    select 'pack_1' , 'banana_2' banana from dual
    union
    select 'pack_1' , 'banana_3' banana from dual
    union
    select 'pack_1' , 'banana_4' banana from dual
    union
    select 'pack_1' , 'banana_5' banana from dual
    union
    select 'pack_1' , 'banana_6' banana from dual
    union
    select 'pack_1' , 'banana_7' banana from dual
    union
    select 'pack_1' , 'banana_8' banana from dual
    union
    select 'pack_1' , 'banana_9' banana from dual
    union
    select 'pack_1' , 'banana_10' banana from dual
    union
    select 'pack_2' , 'banana_11' banana from dual
    union
    select 'pack_2' , 'banana_12' banana from dual
    union
    select 'pack_3' , 'banana_13' banana from dual
    union
    select 'pack_3' , 'banana_14' banana from dual
    union
    select 'pack_3' , 'banana_15' banana from dual
    union
    select 'pack_4' , 'banana_16' banana from dual
    ) t
)
select c.*, ntile(2) over (order by c.id) bucket from c;



IDPACKBANANABUCKET1pack_1banana_112pack_1banana_1013pack_1banana_214pack_1banana_315pack_1banana_416pack_1banana_517pack_1banana_618pack_1banana_719pack_1banana_8210pack_1banana_9211pack_2banana_11212pack_2banana_12213pack_3banana_13214pack_3banana_14215pack_3banana_15216pack_4banana_162

Как видно из примера, banana_8, banana_9 из упаковки pack_1 присвоены 2-ой корзине, что противоречит условию.

Прошу совета.
...
Рейтинг: 0 / 0
20.06.2019, 16:35
    #39828877
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
...
Рейтинг: 0 / 0
20.06.2019, 16:37
    #39828878
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
watsonРавномерно Критерии равномерности?
...
Рейтинг: 0 / 0
20.06.2019, 17:01
    #39828887
watson
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
-2-Критерии равномерности?

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

Staxwatson,

похоже на задачку про рюбзачек
https://www.sql.ru/forum/actualsearch.aspx?search=knapsack&sin=0&bid=3&a=&ma=0&dt=-1&s=1&so=1


http://vbegun.blogspot.com/2005/11/sql-puzzle-iii.html

.....
stax


буду читать, благодарю.
...
Рейтинг: 0 / 0
20.06.2019, 17:06
    #39828888
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
watson,

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

і тд

....
stax
...
Рейтинг: 0 / 0
20.06.2019, 17:11
    #39828892
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
...
Рейтинг: 0 / 0
20.06.2019, 17:17
    #39828897
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
watson-2-Критерии равномерности?
максимально равнымравным чему?
...
Рейтинг: 0 / 0
20.06.2019, 17:28
    #39828903
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
-2-watsonпропущено...

максимально равнымравным чему?

"среднему значению" sum(банан)/к-во корзин

ps
"дисперсия" минимальна
....
stax
...
Рейтинг: 0 / 0
20.06.2019, 18:09
    #39828914
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
Stax"среднему значению" sum(банан)/к-во корзин


Ну тогда greatest(max(размер-упаковки),ceil(sum(банан)/к-во корзин))

SY.
...
Рейтинг: 0 / 0
20.06.2019, 19:34
    #39828932
DВА
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
От блин а я тут на днях голову ломала как файлы данных распределить равномерно по потокам с учетом их объема.
И ничего умнее не придумала, как отсортировать и брать по одну в группу с учетом максимума размера предыдущих групп :))
А нада было погуглить по слову рюкзачек ))
...
Рейтинг: 0 / 0
20.06.2019, 19:45
    #39828938
Кобанчег
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
SYStax"среднему значению" sum(банан)/к-во корзин


Ну тогда greatest(max(размер-упаковки),ceil(sum(банан)/к-во корзин))

SY.Не очень понятно как, например, при упаковках с количеством (1,2,3,10,100) и трех корзинах такой подход распределит
(1,2,3), (10), (100).

Впрочем, еще менее понятно при чём здесь рюкзак.

Я веду речь, когда критерий оптимальности - минимум дисперсии по корзинам.
...
Рейтинг: 0 / 0
20.06.2019, 20:16
    #39828944
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
КобанчегВпрочем, еще менее понятно при чём здесь рюкзак.


Корзина = рюкзак. T.е. есть рюкзаки вместимoстью N упаковок и 5 упаковок с разным количеством товара которые нужно разложить по рюкзакам. Как именно разложить требует уточнения задачи - набить максимально, т.е. (100), (1,2,3,10), пустой (минимизация числа корзин), минимум дисперсии по корзинам (с/без ограничения числа корзин) или ещё чего...

SY.
...
Рейтинг: 0 / 0
20.06.2019, 23:11
    #39828968
watson
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
SYКобанчегВпрочем, еще менее понятно при чём здесь рюкзак.


Корзина = рюкзак. T.е. есть рюкзаки вместимoстью N упаковок и 5 упаковок с разным количеством товара которые нужно разложить по рюкзакам. Как именно разложить требует уточнения задачи - набить максимально, т.е. (100), (1,2,3,10), пустой (минимизация числа корзин), минимум дисперсии по корзинам (с/без ограничения числа корзин) или ещё чего...

SY.

задача забить все корзины/рюкзаки.

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

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

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

похоже, что решение на SQL нетривиальное, поэтому буду писать на pl/sql.

в любом случае, если кто-то напишет на sql, будет любопытно взглянуть. :)
...
Рейтинг: 0 / 0
21.06.2019, 02:19
    #39828975
Кобанчег
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
SYКорзина = рюкзак. T.е. есть рюкзаки вместимoстью N упаковок и 5 упаковок с разным количеством товара которые нужно разложить по рюкзакам.Алгоритмы для задачи о рюкзаке рассчитаны на один рюкзак а не несколько.
И они максимизируют ценность с жестким лимитом на вместимость.
В случае ТС ничего страшного не будет, если какая-то корзина чуть превысит лимит (если мы минимизируем дисперсию).
SYКак именно разложить требует уточнения задачи - набить максимально, т.е. (100), (1,2,3,10), пустой (минимизация числа корзин)Если минимизируем число корзин (странный критерий если цель распределить по n корзинам), то почему бы не засунуть всё в одну.
watsonв любом случае, если кто-то напишет на sql, будет любопытно взглянуть. :)А как ты будешь проверять если не в состоянии озвучить критерий оптимальности?

Минимизация дисперсии корзин требует слишком большой вычислительной сложности.
Полный перебор - корзины в степени упаковки. Его наверняка можно как-то сократить, но все равно будет очень долго.

Соответственно можно смотреть на приближенные распределения, например
1) либо совсем забить на число бананов и распределять по mod(ora_hash(упаковка), число корзин)
2) либо кумулятивную сумму распределять по бакетам
(более-менее нормально работает если нет упаковок больших чем размер корзины.
если такие есть - их предварительно можно определить в отдельные корзины)
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
with c(id, pack, amount)
as
(
select 0, 'pack_0', 20 from dual
union all
select 1, 'pack_1', 10 from dual
union all
select 2, 'pack_2', 3 from dual
union all
select 3, 'pack_3', 2 from dual
union all
select 4, 'pack_4', 1 from dual
),
t as
(select c.*,
        sum(amount) over (order by amount) x,
        sum(amount) over () total
   from c)
select t.*,
       width_bucket(x, 0, total + 1e-10, 3) bkt0,
       -- или что то же самое
       ceil(x / (total / 3)) bkt1
  from t
order by 1;

        ID PACK       AMOUNT          X      TOTAL       BKT0       BKT1
---------- ------ ---------- ---------- ---------- ---------- ----------
         0 pack_0         20         36         36          3          3
         1 pack_1         10         16         36          2          2
         2 pack_2          3          6         36          1          1
         3 pack_3          2          3         36          1          1
         4 pack_4          1          1         36          1          1

Все будет уже не так симпатично если 20 заменить на 30 или вообще 100.
...
Рейтинг: 0 / 0
21.06.2019, 06:41
    #39828989
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
watsonто есть изначальное множество данных надо разделить по потокамЗадача параллельной обработки решается проще - очередь.
...
Рейтинг: 0 / 0
21.06.2019, 07:08
    #39828993
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
Кобанчег(более-менее нормально работает если нет упаковок больших чем размер корзины .
если такие есть - их предварительно можно определить в отдельные корзины)Корзина имеет неограниченный объем. Если есть упаковки более среднего, то каждая из них "предварительно" идет в отдельную корзину, но это не исключает корзины из дальнейшего распределения.
Алгоритм последовательного раскладывания упаковок можно улучшить, если упаковки сортировать по убыванию и на каждой итерации выбирать пустейшую корзину.
...
Рейтинг: 0 / 0
21.06.2019, 08:39
    #39829012
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
SYКобанчегВпрочем, еще менее понятно при чём здесь рюкзак.


Корзина = рюкзак. T.е. есть рюкзаки вместимoстью N упаковок и 5 упаковок с разным количеством товара которые нужно разложить по рюкзакам. Как именно разложить требует уточнения задачи - набить максимально, т.е. (100), (1,2,3,10), пустой (минимизация числа корзин), минимум дисперсии по корзинам (с/без ограничения числа корзин) или ещё чего...

SY.
імхо
Корзина = рюкзак. T.е. есть рюкзаки вместимoстью N бананов ...

.....
stax
...
Рейтинг: 0 / 0
21.06.2019, 09:00
    #39829019
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
DВАИ ничего умнее не придумала, как отсортировать и брать по одну в группу с учетом максимума размера предыдущих групп :))Следующего в сторону уменьшения класть в наипустейшую "корзину"? - Простой и понятный алгоритм без изысков. "Палатки" здесь не нужны.
...
Рейтинг: 0 / 0
21.06.2019, 09:16
    #39829023
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
-2-упаковки сортировать по убыванию и на каждой итерации выбирать пустейшую корзину.Пример неоптимального результата деления 7,8,3,2,2 по двум корзинам:
Код: plsql
1.
2.
3.
4.
    BASKET AMOUNT CONTENT                       
---------- ------ ------------------------------
         1     12 pack_1+8,pack_3+2,pack_4+2    
         2     10 pack_0+7,pack_2+3             
...
Рейтинг: 0 / 0
21.06.2019, 12:29
    #39829150
Sayan Malakshinov
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
-2-Пример неоптимального результата деления 7,8,3,2,2 по двум корзинамВ общем-то, достаточно хорошее компромиссное решение с отклонением от оптимального всего в ±1, зато затраты всего лишь на сортировку. В принципе, его можно немного улучшить (в случае диспетчера очередей, т.е. когда диспетчер знает у какой очереди сколько еще осталось обработать) - при снижении кол-ва необработанных до допустимого, переходить на полный перебор.
...
Рейтинг: 0 / 0
21.06.2019, 13:19
    #39829176
Кобанчег
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
-2-Кобанчег(более-менее нормально работает если нет упаковок больших чем размер корзины .
если такие есть - их предварительно можно определить в отдельные корзины)Корзина имеет неограниченный объем. Если есть упаковки более среднего, то каждая из них "предварительно" идет в отдельную корзину, но это не исключает корзины из дальнейшего распределения.Под размером понимался ожидаемый размер = число бананов/число корзин.
В примере выше, если имеем 100 для одной из упаковок, убираем ее (в третью корзину) и уменьшаем число корзин на 1.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
with c(id, pack, amount)
as
(
-- select 0, 'pack_0', 100 from dual
-- union all
select 1, 'pack_1', 10 from dual
union all
select 2, 'pack_2', 3 from dual
union all
select 3, 'pack_3', 2 from dual
union all
select 4, 'pack_4', 1 from dual
),
t as
(select c.*,
        sum(amount) over (order by amount) x,
        sum(amount) over () total
   from c)
select t.*,
       width_bucket(x, 0, total + 1e-10, 3 - 1) bkt0,
       -- или что то же самое
       ceil(x / (total / (3 - 1))) bkt1
  from t
order by 1;

        ID PACK       AMOUNT          X      TOTAL       BKT0       BKT1
---------- ------ ---------- ---------- ---------- ---------- ----------
         1 pack_1         10         16         16          2          2
         2 pack_2          3          6         16          1          1
         3 pack_3          2          3         16          1          1
         4 pack_4          1          1         16          1          1


-2-Алгоритм последовательного раскладывания упаковок можно улучшить, если упаковки сортировать по убыванию и на каждой итерации выбирать пустейшую корзину.Выглядит более изящно, но интересно реализуемо ли SQL-но без model/rec with.
Напоминает заправки .
...
Рейтинг: 0 / 0
21.06.2019, 14:08
    #39829212
Кобанчег
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
StaxКорзина = рюкзак. T.е. есть рюкзаки вместимoстью N бананов ... Максимально набить один рюкзак или равномерно набить n рюкзаков это вообще перпендикулярные вещи.
Единственно, что общее это экспоненциальная сложность полного перебора, так что да, в этом схожесть на подход Бегуна.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
with tt(ord, x)
     as (select rownum, column_value from table(sys.odcinumberlist(1, 2, 3, 10, 100))),
     t0 as (select rownum n from dual connect by level <= power(3, 5)),
     t1 as (select n, mod(trunc(n / power(3, ord - 1)), 3) basket, sum(x) amount,
                   listagg(x, ', ') within group (order by x) items
              from t0 cross join tt
             group by n, mod(trunc(n / power(3, ord - 1)), 3)),
     t2 as (select t1.*,
                   variance(amount) over (partition by n) v,
                   count(*) over (partition by n) cnt
              from t1)
select distinct
       listagg(amount, ', ') within group (order by amount) baskets,
       listagg('(' || items || ')', ', ') within group (order by items) items
  from (select t2.*, rank() over (order by v) rnk
          from t2
         where cnt = 3)
 where rnk = 1
 group by n;

BASKETS                        ITEMS
------------------------------ ------------------------------
6, 10, 100                     (1, 2, 3), (10), (100)
...
Рейтинг: 0 / 0
21.06.2019, 15:13
    #39829257
Valergrad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
Кобанчег,

На всякий случай замечу, что если решать задачу в формулировке ТС - "минимизировать дисперсию", то количество корзин всегда равно 1. Просто пихай все в одну корзину, дисперсия 0, все абсолютно равномерно разделилось. Меньше нуля дисперсию получить нельзя.
Есть ощущение что ТС и сам не очень хорошо представляет чего он хочет. Но если он хочет разделить данные на потоки, то предположу что он хотя бы знает сколько потоков он хочет. Предположим он хочет N потоков. Тогда нам нужен бинарный поиск по variance - разнице между максимальной и минимальной корзиной. При фиксированном variance мы легко определим сколько должно быть в максимальной корзине - пусть это K. Выделить из ящиков поднабор ящиков общей суммой K можно без полного перебора с помощью динамического программирования ( гуглить по "задача о рюкзаке динамическое программирование" ). От стандартной задачи это отличается тем что нам нужно найти не одно решение, а все ( т.к. для каких-то из этих решений может не оказаться решений на следующей итерации, поэтому мы вынуждены проверить все). После чего решаем ту же задачу для оставшихся ящиков и корзины на одну меньше и с уже известным variance.
Это решение работает гораздо быстрей чем полный перебор.
...
Рейтинг: 0 / 0
21.06.2019, 15:43
    #39829280
DВА
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
ElicDВАИ ничего умнее не придумала, как отсортировать и брать по одну в группу с учетом максимума размера предыдущих групп :))Следующего в сторону уменьшения класть в наипустейшую "корзину"? - Простой и понятный алгоритм без изысков. "Палатки" здесь не нужны.
да, но не гарантирующий (?) максимально равномерного распределения
...
Рейтинг: 0 / 0
21.06.2019, 15:46
    #39829282
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разделить количество бананов в упаковке по корзинам - buckets (SQL?)
DВАда, но не гарантирующий (?) максимально равномерного распределенияА так ли оно надо?
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Разделить количество бананов в упаковке по корзинам - buckets (SQL?) / 25 сообщений из 30, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]