3

I am re-developing a legacy system that matches a basket of user selected retail products into one or more valid promotions. These promotions are the industry standard BOGOF (buy one get one free), buy two get third free, buy product X and Y and get 10% off, etc... but all require that you can filter the list of potential items into those that satisfy these promotions.

I would like the solution to take an entire basket of retail items and analyse them in one operation, as opposed to the incumbent method of matching a single product as and when it is ordered. (The current solution leads to undesirable limitations)

Each promotion has a series of qualifying products that must be present in order to trigger the promotion. These are arranged in n number of sets (or positions), for example:

Example "Buy two get third free" Promotion =

| Item 1 |             | Item 1 |             | Item 2 |
|   or   |             |   or   |             |   or   |
| Item 2 |     AND     | Item 4 |     AND     | Item 6 |
|   or   |             |   or   |             |   or   |
| Item 3 |             | Item 9 |             | Item 4 |

  Set 1                   Set 2                  Set 3

Each promotion must have exactly one product from each group present, unless the item appears in the same set multiple times. The promotion can have an unlimited (but usually < 10) 'sets' of products.

As a simple example a shopping basket of Item 1, Item 4 and Item 6 would trigger the promotion, similarly the basket of Item 1, Item 1 and Item 2 would also trigger it. However the basket of Item 1, Item 2 and Item 3 would not as each set is not satisfied.

Aside from the obivious question of the best way to detect when a promotion has been triggered, I will also need to recover the set (position) that the item had been matched into to handle the detail of the pricing etc. It would also be desirable if more expensive (in currency terms) items are favoured over less expensive (equally matched) items when assigning them to the promotion.


Hopefully the next part will aid a solution, not sound so unclear that it will create unnecessary noise, feel free to disregard !

My best solution so far is to create a new set for each retail item in the "shopping basket" holding the promotion set (position) that this item will satisfy. ie.

Item 1 satisifies sets: {1,2}
Item 4 satisifies sets: {2,3}
Item 6 satisifies sets: {3}

Then my theory is that you "check" that this list of sets contains a unique item in each position and that each promotion position is filled. So far my working examples all use brute force, loops or recursion to produce all combinations of the sets (above) in an attempt to check if there is a unique combination. This scales very very badly and with anything other than a very trivial example doesn't work at all in the real world. (This function will be called in realtime as items are added to a basket, so needs to be quick)

Lots of research suggest that Bipartite matching would produce some desired outcome, but I can only find research articles and fairly complex mathematical texts on the subject. Some pseudo code or basic logic would be great.


My two questions are basically:

1) Does anybody see a better/quicker/simpler way of analysing the customer basket to produce matching promotions.
2) Assuming I have identified the most efficient way of matching items into the relevant positions, what is the least expensive way of determining the list of retail items to record against the promotion.

Any assistance would be gratefully received as I can no longer see light at the end of the tunnel! (The final solution will be in .NET and we use SQL server 2008 R2.)

blahdiblah
  • 33,069
  • 21
  • 98
  • 152
Nick Williams
  • 95
  • 1
  • 9
  • A quick clarification - why wouldn't items `1,2,3` satisfy your example? Item 1 satisfies {1,2}, Item 2 satisfies {1,3}, Item 3 satisfies {1}. So we can have Item 3 satisfy {1}, Item 1 satisfy {2}, and Item 2 satisfy {3}. Unless I'm missing something – Mshnik Jan 21 '16 at 17:44
  • How many sets are there per promotion? Any given promotion can be reduced to a state machine but the number of states scales quickly with the number of sets. – QuestionC Jan 21 '16 at 18:54

1 Answers1

2

Checking each promotion for validity on a given shopping cart can be reduced to Max Flow. In describing my solution I am assuming you are able to implement and solve a graph-based Max flow problem. If not that is a second problem to solve (and luckily a much more general one).

Let the input to the algorithm be as follows:

  • A set of all valid items I. Not necessarily used in final coding of algorithm.
  • A shopping cart C of size n, a subset of I containing items C_1 ... C_n. Thus C = {C_i}fori = 1...n
  • A single promotion P consisting of m subsets, each holding a variable number of items. Each subset S is a subset of I. Each subset cannot have duplicates, but a single item can be present across multiple subsets.

Construct a graph G as follows:

  • Add a super source node, labeled SOURCE
  • Add a super sink node, labeled SINK
  • For each unique item C_i in shopping cart C, add an available item node A_i, then add an edge from SOURCE to A_i with capacity equal to the number of occurrences of C_i in C.
  • For each subset S_i in promotion P, add the following:
    • A single set node S_i, and an edge from S_i to SINK with capacity 1.
    • For each required item I_j for S_i, a required item node B_i_j, and an edge from B_i_j to S_i with capacity 1.
  • Finally, for each pair of nodes A_x and B_y such that the items they represent are equivalent, an edge from A_x to B_y with capacity 1.

Finally, run a max flow algorithm with SOURCE as the source and SINK as the sink. If the resulting max flow has value equal to the number of subsets (m), then output true - the promotion can be satisfied by this shopping cart. Otherwise output false - the promotion cannot be satisfied by this shopping cart.

For example, for your set example, with the shopping cart {1,1,4,6}, the following graph should be created:

Sample graph for example


Expected time complexity, where # of items is n, and number of subsets in promotion is m:

  • Graph construction:
    • Adding SOURCE and SINK - O(1)
    • Adding unique items from cart and edges from source - O(N)
    • Adding subsets and required item nodes, and edges between - O(N*M)
    • Adding edges from subset nodes to sink - O(M)
    • Adding edges between corresponding item nodes - O(N^2)
    • Total - O(N^2 + N*M) = O(N * (N+M))
  • Max Flow Algorithm - see wikipedia page. Simple implementation cost - O((N*M)^3). Can be improved with a more complex algorithm.
  • Retrieving solution - O(1).
Mshnik
  • 7,032
  • 1
  • 25
  • 38