I have a list of items I want to buy. The items are offered by different shops and different prices. The shops have individual delivery costs. I'm looking for an optimal shopping strategy (and a java library supporting it) to purchase all of the items with a minimal total price.
Example:
- Item1 is offered at Shop1 for $100, at Shop2 for $111.
- Item2 is offered at Shop1 for $90, at Shop2 for $85.
- Delivery cost of Shop1: $10 if total order < $150; $0 otherwise
- Delivery cost of Shop2: $5 if total order < $50; $0 otherwise
- If I buy Item1 and Item2 at Shop1 the total cost is $100 + $90 +$0 = $190.
- If I buy Item1 and Item2 at Shop2 the total cost is $111 + $85 +$0 = $196.
- If I buy Item1 at Shop1 and Item2 at Shop2 the total cost is $100 + $10 + $85 + $0 = 195.
I get the minimal price if I order Item1 and Item2 at Shop1: $190
What I tried so far
I asked another question before that led me to the field of constraint programming. I had a look at cream and choco, but I did not figure out how to create a model to solve my problem.
| shop1 | shop2 | shop3 | ...
-----------------------------------------
item1 | p11 | p12 | p13 |
item2 | p21 | p22 | p23 |
. | | | |
. | | | |
-----------------------------------------
shipping | s1 | s2 | s3 |
limit | l1 | l2 | l3 |
-----------------------------------------
total | t1 | t2 | t3 |
-----------------------------------------
My idea was to define these constraints:
- each price "p xy" is defined in the domain (0, c) where c is the price of the item in this shop
- only one price in a line should be non zero
- if one or more items are bought from one shop and the sum of the prices is lower than limit, then add shipping cost to the total cost
- shop total cost is the sum of the prices of all items in a shop
- total cost is the sum of all shop totals
The objective is "total cost". I want to minimize this.
In cream I wasn't able to express the "if then" constraint for conditional shipping costs.
In choco these constraints exist, but even for 5 items and 10 shops the program was running for 10 minutes without finding a solution.
Question
How should I express my constraints to make this problem solvable for a constraint programming solver?
I have implemented this problem in MiniZinc (a high level constraint programming language): shopping_basket.mzn. It is quite forward and maybe could be used as a model for your Java model.
For the Choco model, have you tried different search strategies? A different strategy may be faster.
By the way, one other Java constraint programming solver you may want to check out is JaCoP.
What you are asking about is in essence the k-knapsack problem. The wikipedia page I liked has a wealth of resources on solutions for it. The problem is however NP-Complete to solve in entirety, so what you may wish to do is look for a close to best solution through simulated annealing or other forms for search through the problem space.
The first thing to remember is that in constraint problems you will probably end up taking a good chunk of time to generate a solution. In your previous example, though five items and ten stores seems small it, in reality, generates a large problem space (on the order of 1e5 not including the added complication of the conditional pricing which further engrosses the problem).
The constraints on the problem are that you buy one of each item. The goal is minimal price. I think what you have is fairly good, though I'm not too sure about bullet points one and two.
I would consider amortizing the shipping over the cost of the items bought rather than adding it on as a total value when doing the calculations.
I'm not too sure this is a k-knapsack problem. The question did mention the words "shopping baskets" but did not specify a capacity to any given shipment. If you specified a maximum shipment size, then the problem starts looking more like a knapsack problem.
The problem is really just a basic network flow problem with transporation costs on the arcs and costs at the origin. Because you have a clear objective function - minimize transportation + product cost and because there is likely to be only one solution, CP may not be the best approach.
Consider solving as linear programming problem:
Min: Transportation + Product Cost
ST: Total product shipped >= Demand (for each product)
You might need to develop some piecewise linear equations for the transportation cost, but that shouldn't be a problem.