Как создать алгоритм, который будет продолжать работать алгоритм до успеха в Java - PullRequest
0 голосов
/ 16 января 2019

У меня есть пакет (https://github.com/skjolber/3d-bin-container-packing/), который будет упаковывать вещи в контейнер для меня. Однако, если есть слишком много предметов, например, 1000 рубашек, и только 500 помещаются в самый большой контейнер, который у нас есть), он не будет пытаться упаковать оставшиеся 500, результат просто возвращает ноль и не пытается объединить доступные контейнеры.

Я решаю проблему с упаковкой в ​​мусорное ведро. Обратите внимание, что это не нужнобыть точным решением, поскольку мы просто собираем калькулятор затрат на перевозку. Я наткнулся на пакет, который решает большую часть проблемы. В основном у меня есть 5 контейнеров, которые можно использовать. API получает запрос с продуктами, и я собираю размеры иЯ хотел сначала проверить, был ли пакет успешным, а затем добавить его в объект List packageResults, чтобы у меня был список. Но как этот пакет настроен, я подозреваю, что он не будет работать без потерицелостность продуктов.

Вот конструктор службы

public PackingService(List<Product> products) 
{
    containers = SetContainers();
    this.packer = new LargestAreaFitFirstPackager(containers);
    this.products = products;
    PrepareProductsToPack(products);
}

фактический способ упаковки

public List<Container> PackItems()
{
    packedResultContainers = new ArrayList<Container>();
    Container results =  packer.pack(productsToPack);
    return this.packedResultContainers;
}

и, наконец, я взял свой список сущностей Product и подготовил их для алгоритма упаковки.

    productsToPack = new ArrayList<BoxItem>();
    for(Product product : products)
    {
        for(int i = 1; i < product.getQuantity(); i++)
        {
            productsToPack.add(new BoxItem(new Box(product.getSku(),
                                                    product.getProductDimensions().getRoundedWidth(),
                                                    product.getProductDimensions().getRoundedDepth(),
                                                    product.getProductDimensions().getRoundedHeight(),
                                                    product.getProductDimensions().getRoundedWeight())));
        }
    }

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

Может ли кто-нибудь дать представление о том, как я могу настроить свой алгоритм, чтобы справиться с этим?

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

Я обновляю свой ответ для будущих пользователей, именно так я решил проблему с упаковкой в ​​бин

public ArrayList<Container> PackItems()
{
    this.packingResults = new ArrayList<Container>();
    productSetsToPack = chopped(productsToPack, getInitBoxCount(productsToPack));
    int hashMapId = 0;
    for(int i = productSetsToPack.size()-1; i >= 0; i--)
    {
        ArrayList<BoxItem> itemsToPack = productSetsToPack.get(i);
        productSetsMap.put(hashMapId, itemsToPack);
        pack(itemsToPack, hashMapId, 5); //pack largest sized boxs
        ++hashMapId;
    }; 

    for (Map.Entry<Integer, Container> entry : packedContainerMap.entrySet()) {
        int containerKey = entry.getKey();
        Container packedContainer = entry.getValue();
        int smallestBoxSize = getSmallestBox(productSetsMap.get(containerKey), Integer.parseInt(packedContainer.getName()));
        packingResults.add(pack(productSetsMap.get(containerKey), smallestBoxSize));
        // ...
    }
    return packingResults;
}

Ответы [ 3 ]

0 голосов
/ 16 января 2019

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

Это, конечно, не очень хорошо масштабируется. Id также генерирует подмножества, используя список индексов вместо ссылок (Добавьте все элементы в список, создайте набор чисел от 0 до list.size (), затем сгенерируйте все подмножества этого набора.)

0 голосов
/ 16 января 2019

бу, То, что вы хотите, очень возможно. Это будет довольно сложным делом, особенно если у вас 5 разных размеров упаковки. Я бы предложил использовать рекурсию.

создайте метод, который находит наименьшее количество самых больших пакетов, в которые может поместиться ваш заказ. допустим, он помещается в 4 больших ящика. затем возьмите каждую большую коробку и попытайтесь упаковать ее в меньшие коробки. трассы будут выглядеть примерно так, где прямоугольник 5 - самый большой прямоугольник, а прямоугольник 1 - самый маленький прямоугольник.

box5 - box5 - box5- box5
box5 - box5 - box5- box4
box5 - box5 - box5- box3
box5 - box5 - box5- box2
box5 - box5 - box5- box1

этот пробег уместился бы в 3 больших коробки и 1 маленькую коробку.

Код для поиска наибольшего поля, вероятно, будет циклом while, подобным

int boxCount = getInitBoxCount(products);

public int getInitBoxCount(ArrayList<BoxItems> items)
{
    if(productsFit(products,sizeLarge) == null)
    {
        ArrayList<BoxItems> temp1 = new ArrayList<BoxItems>();
        ArrayList<BoxItems> temp2 = new ArrayList<BoxItems>();

        for(int x = 0; x < items.length ; x++)
        {
           if(x > items.length/2)
           {
               temp1.add(items.get(x)) 
           }
           else
           {
               temp2.add(items.get(x))
           }
        }
        return getInitBoxCount(temp1) + getInitBoxCount(temp2);
    }
    return 1;
}

Это будет постоянно разделять ваш список BoxItems пополам, пока он не будет соответствовать количеству ящиков

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

Следующими 2 шагами будет создание рекурсивного способа обрезки размера поля, такого как

// 5 is the largest

public int getSmallestBox(int boxsize,ArrayList<BoxItems> items)
{
    if(productsFit(boxsize -1)!= null)
    {
        return getSmallestBox(boxsize -1, items)
    }
    else
        return boxsize;
}

И это получит самую маленькую коробку, в которую мы сможем поместиться. Последнее, что вам нужно проверить, это комбинирование ящиков. Вы можете обнаружить, что у вас есть 4 маленьких коробки, и вы можете объединить их в 2 средних коробки. после того, как вы сможете комбинировать и сокращать поля, вы сможете отслеживать результаты после каждого запуска. Таким образом, общий поток программы будет выглядеть примерно так в грубом псевдокоде.

Container[getInitBoxCount()] shipments //create an array of containers with the size of the inital box count 

for(Container c : shipments)
{
    c = new LargeContainer();
}


Container[] check; //create new objects into the check array. dont set one array = to anoter

do
{
    check = shipments //create new objects into the check array. dont set one array = to anoter
    for(Container c: shipments)
        getSmallestBox(5, c);
    combineBoxes(shipments);
}
while(check == shipments)
0 голосов
/ 16 января 2019

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

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