-1

i have a combinatorial optimization problem.

I have X bids containing a price and n rows. The price is the total price for these n rows. n can be between 1 and 12. All rows have a number attached (1-12). This means all in all there are 12 different rows. A bid can never have the same row twice. I can either accept a bid or decline it. It is not possible to somehow divide the bid into two (or more).

Now I have a Bit array with a length of 12 Bits telling me for each and every row if I need that row or not.

What I want is to calculate the cheapest possible allocation for the rows that I need. Having a headache I am not able to solve this problem at the moment. Maybe one of you guys can help me a little.

Here my simple Bid class:

public class Bid {
    private int price;
    private int[] rows; // e.g. rows[0] = 3 means this bid contains row 3
    private int connectionID;

    public Bid(int price, int[] rows, int connectionID) {
        super();
        this.price = price;
        this.rows = rows;
        this.connectionID = connectionID;
    }

    public int getPrice() {
        return price;
    }

    public int[] getRows() {
        return rows;
    }

    public int getConnectionID() {
        return connectionID;
    }   
}

Thanks a lot!

Ps.: The ConnectionID helps me to identify the Bids.

Daniel
  • 43
  • 1
  • 1
  • 4

1 Answers1

1

There is a really obvious way: try every subset. That's not great when you had 30 items and therefore 230 subsets, but it's alright if you don't mind waiting a bit. It's not something that would take months.

But we can do better, at least on average.

Technique #1, prune useless trees from the search space. If you organize the search as an implicit binary tree which makes choices for each item "do I take this or not", then there will be sub-trees that you can decide are pointless before you're all the way at the bottom. The simplest one is just to have the sum of weights of all the items so far that you've tentatively chosen to take, if that's more than the cheapest solution that you've found so far then it's not going to improve later (assuming you have no negative prices, which you don't because if there were any negative prices then you just take all of them for sure and then don't include them in this search). This alone will probably make a big difference already.

Technique #2, avoiding dead ends. If there is only 1 bid left that has a certain row that you haven't included yet (all the other, if any, bids that have that row were tentatively decided to be not included), then there's nothing to decide, you have to take it. This can of course force the cost to become higher than the best found, see #1.

Technique #3, use an admissible heuristic to prune even more. For example, a trivial one: say some row is not yet covered. Clearly in order to produce a solution, it must become covered, so the cheapest way to do that can be added to the running total before deciding whether this branch can be pruned. You can't just add the sum of all of the minimum costs for all uncovered rows though, because the same bid could cover several of them, but if you take the maximum instead of the sum it will work. There are better tricks here, but this one is simple.

harold
  • 61,398
  • 6
  • 86
  • 164