I'm looking for an algorithm for the following problem:
I have a set of x distinct components and a set of y supplier for those components. I know the price p(x,y) for each component from each supplier. I also know the shipping cost s(y) for each supplier, which is obviously cheaper if you just buy from just a few suppliers. Not all suppliers have each component available. I want to buy all components once, but need to get the cheapest total price or at least a very closed small value.
The straight forward approach would be to try each combination, which could take some time if x and y get very large, although it could be parallelized. Any suggestions are appreciated.
For simplicity let's say x = 100, y = 1000.
Thanks for all the comments. They pointed me in the right direction, to formulate the problem like displayed below.
Minimize the sum of all items plus shipping costs:
p(0,0)*x00 + p(0,2)*x02 + p(1,2)*x12 + ... + ship(0)*y0 + ship(1)*y1 + ...
with x and y in [0,1], p(n,m) is the price of item n for supplier m and ship(m) is the shipping cost for supplier m
Subject to:
Retrieve each item exactly one time, like this:
p00 + p01 = 1
p12 + p13 + p15 = 1
p20 + p21 = 1
...
Shipping cost is taken into account if one item is bought from this supplier
y0 >= x00
y0 >= x10
y1 >= x01
...
Related
I have the below problem:
Mary intends to purchase a cupboard of volume at least X mm^3. For every positive whole number n, there exists a unique cupboard that Mary can buy for ānā pounds, and the unique cupboard would have the measurements: depth (5n + 5) mm, width (5n) mm and height (2^n) mm.
I need to come up with an algorithm that runs in Olog((logX)) worst case time that calculates the least amount Mary has to pay to purchase an appropriate cupboard.
I can only think of an O(logX) solution with binary search. Help would be much appreciated.
my solution below in python:
import math
# scanning the input for X
X = input("Enter a value:\n")
left = 0
right = math.log(int(X),2)
final = 0
while (left <= right):
middle = (left + right) // 2;
temp_vol = 5 * middle * (5 * middle + 5) * (2**middle);
if (temp_vol >= int(X)):
final = middle;
right = middle - 1;
else :
left = middle + 1;
print(f'the min pay out is: {final}')
If you perform linear search by n value (just simple n incrementing loop), then volume rises exponentially, so you reach volume X in log(X) steps
When you perform binary search by n value, you make log(log(X)) steps, so your solution is already fine.
Below is the covariance equation for two variables, ABC and XYZ.
Below is the algorithm to find the covariance between ABC and XYZ.
Algorithm 1: Calculate Covariance
1. cov = 0
2. for i = 0 to size - 1
3. cov = cov + (return_abc[i] - avg_abc) * (return_xyz[i] - avg_xyz)
4. end for
5. cov = cov / size - 1
6. end
How do I design an algorithm to find the covariance between one variable to the rest of the variables in a sample?
For example, how do I find the covariance between APPLE's stock and the rest of the stocks in NASDAQ (about 3,100 companies) ?
http://www.investopedia.com/articles/financial-theory/11/calculating-covariance.asp
If you're looking at only end of day prices (for simplicity), and you would like to compare a single stock to all of the rest of the stocks, try treating the rest of them all as one element, ie:
n=number of days to analyze
marketReturn = average(return of each stock that isn't APPLE)
marketAverage = (sum of marketReturn's)/n
appleAverage = (sum of APPLE returns)/n
then apply the summation across a sample size of the number of days you are analyzing.
Answer = (((day 1 APPLE return %)-(appleAverage))*((day 1 marketReturn %)-(marketAverage)) + ((day 2 APPLE return %)-(appleAverage))*((day 2 marketReturn %)-(marketAverage)) + ...)/(n-1)
I suppose if you want to check each stock individually:
for(x=0;x<numStocksNotAPPLE;++x)//increment through each stock
{
covariantList[x]=(((day 1 APPLE return percent)-(appleAverage))*((day 1 stock[x] percent)-(stock[x] average)) + ... + (((day n APPLE return %)-(appleAverage))*((day n stock[x] %)-(stock[x] average)))/(n-1)
}//that should give you a covariant APPLE vs each stock
and then if you want just one number, you could take the average of the covariantList:
foreach(covariantList c)
{
sum+=c
}
averageCovariant = sum/covariantList.size
Keep in mind this is all psuedo-code, i'm not claiming any of it is functional
I have to buy 100 Products ( or p Products) from 20 Vendors ( or v Vendors). Each Vendors have all of these Products, but they sell different Price.
I want to find the best price to get 100 Products. Asume that there is no Shipping Cost.
There are v^p ways. And I will get only one way that have best Price.
The problem seem to be easy if there is no requirement: LIMIT number of Vendors to x in the Orders because of Time Delivery ( or Some reasons).
So, the problem is: Find the best way to buy p Product from limit x Vendors ( There are v Vendors , x<=v).
I can generate all Combination of Vendors( There are C(v,x) combinations) and compare the Total Price. But There are so many combinations . (if there are 20 Vendors, there are around 185k combinations).
I stuck at this idea.
Someone has same problem , pls help me. Thank you very much.
This problem is equivalent to the non-metric k-center problem (cities = products, warehouses = vendors), which is NP-hard.
I would try mixed integer programming. Here's one formulation.
minimize c(i, j) y(i, j) # cost of all of the orders
subject to
for all i: sum over j of y(i, j) = 1 # buy each product once
for all i, j: y(i, j) <= z(j) # buy products only from chosen vendors
sum over j of z(j) <= x # choose at most x vendors
for all i, j: 0 <= y(i, j) <= 1
for all j: z(j) in {0, 1}
The interpretation of the variables is that i is a product, j is a vendor, c(i, j) is the cost of product i from vendor j, y(i, j) is 1 if we buy product i from vendor j and 0 otherwise, z(j) is 1 is we buy from vendor j at all and 0 otherwise.
There are many free mixed integer program solvers available.
Not Correct as shown by #Per the structure lacks optimal substructure
My assumptions are as follows, from the master table you need to create a sub list which has only "x" vendor columns, and "Best Price" is the "Sum" of all the prices.
Use a dynamic programming approach
What you do is define two functions, Picking (i,k) and NotPicking(i,k).
What it means is getting the best with ability to pick vendors from 1,.. i with maximum of k vendors.
Picking (1,_) = Sum(All prices)
NotPicking (1,_) = INF
Picking (_,0) = INF
NotPicking (_,0) = INF
Picking (i,k) = Min (Picking(i-1,k-1) + NotPicking(i-1,k-1)) - D (The difference you get because of having this vendor)
NotPicking (i,k) = Min (Picking(i-1,k) + NotPicking(i-1,k))
You just solve it for a i from 1 to V and k from 1 to X
You calculate the difference by maintaining for each picking the whole product list, and calculating the difference.
How about using a Greedy Approach. Since you have a limitation on the vendors ( you need to use at least x of the total v vendors). That means you need to choose at least 1 product from each vendor of the x ... And here's an example solution:
For each vendor in v, sort the products by price, then you will have "v" sets of sorted prices. Now you can pick the min of these sets and sort again, producing a new set of "v" products, containing only the cheapest ones.
Now, if p <= v, then pick the first p items and you are done, otherwise pick all v items and repeat the same logic until you reach p.
I haven't worked this out and verified, but I guess it might work. Try this:
Add two more columns called "Highest Price" and "Lowest Price" to the table and generate data for it: they should hold the highest and lowest price for each product amongst all vendors.
Also add another column, called "Range" which should hold the (highest price - lowest price).
Now do this 100 (p) times:
Pick the row with highest range. Buy the product with least price on
that row. Once bought, mark that cell as 'bought' (maybe set null).
Recalculate lowest price, range for that row (ignoring cells marked as 'bought').
EDIT: Hungarian algorithm is not the answer to your question unless you did not wanted to put a limit on vendors.
The algorithm you are looking for is Hungarian Algorithm.
There are many available implementations of it on the web.
I've been unable to match this problem into some canonical one, and I would like some guides to build/use an algorithm and solve it. Description is as follows:
We have some people who want breakfast. Each one may order any number of coffee, juice and toast. We accumulate the order for all the group.
InitialOrder = { C1, J1, T1 } with C1, J1, T1 being integer non-negative numbers.
Each component has a given price, so the total price of the initial order is
InitialPrice = C1 * Pc + J1 * Pj + T1 * Pt with Pc, Pj, Pt being rational positive numbers
Cafeteria has also 'breakfast menus' consisting in combinations of standard items
full breakfast = coffee + juice + toast
normal breakfast = coffee + toast
bread breakfast = 2 toast
Choosing these menus is cheaper than choosing each component separately, so we have
Pf < Pc + Pj + Pt
Pn < Pc + Pt
Pb < 2 * Pt
with Pf, Pn, Pb being rational positive numbers
People want to group the initial order into menus to minimize the total amount spent. Then
FinalOrder = { C2, J2, T2, F, N, B } with C2, J2, T2, F, N, B integer non-negative numbers
and we'll have a FinalPrice <= InitialPrice as
FinalPrice = C2 * Pc + J2 * Pj + T2 * Pt + F * Pf + N * Pn + B * Pb with Pc, Pj, Pt, Pf, Pn, Pb as rational positive numbers
All prices (Pc, Pj, Pt, Pf, Pn and Pb) are known in advance.
Please, do you know Which approach should I follow to build an algorithm to minimize FinalPrice for a given InitialOrder? Feel free to ask any more details you need.
Thank you in advance.
This looks like a Linear Integer Programming problem.
You have six variables and a linear equation (for final price) which you need to minimize, given linear constraints (must match initial order). The restriction being that the variables are non-negative and take integer values.
For instance in your example case it will be (I am presuming your actual problem is more complicated than your example :-))
Minimize
C2 * Pc + J2 * Pj + T2 * Pt + F * Pf + N * Pn + B * Pb
(Multiply Pc etc with a suitable integer to make them integers if needed)
Subject to the constraints that
C2 + F + N = C1
T2 + F + N + 2B = T1
J2 + F = J1
In the general case, Integer Programming is NP-Hard, but given the small size of the problem and the constraints, standard solving techniques can probably quickly solve it for you.
Hope that helps.
If you don't want to go the whole hog (integer linear programming, which is a reasonably complex area), consider an exhaustive tree search using branch-and-bound. BnB is essentially depth-first search where you backtrack at any point where the cost of the current branch is greater than or equal to the best solution you have found so far.
As Moron says, though, for any large problem you're going to need ILP.
Since your problem is closely related to bin packing (or at least the vector version of it), some of the associated heuristics might also come in handy. Specifically, a greedy heuristic where you greedily pack full breakfasts (or 2*normal + toast depending on the relative costs) first, and then continue in this vein, might suffice.
Here is my problem. Imagine I am buying 3 different items, and I have up to 5 coupons. The coupons are interchangeable, but worth different amounts when used on different items.
Here is the matrix which gives the result of spending different numbers of coupons on different items:
coupons: 1 2 3 4 5
item 1 $10 off $15 off
item 2 $5 off $15 off $25 off $35 off
item 3 $2 off
I have manually worked out the best actions for this example:
If I have 1 coupon, item 1 gets it for $10 off
If I have 2 coupons, item 1 gets them for $15 off
If I have 3 coupons, item 1 gets 2, and item 3 gets 1, for $17 off
If I have 4 coupons, then either:
Item 1 gets 1 and item 2 gets 3 for a total of $25 off, or
Item 2 gets all 4 for $25 off.
If I have 5 coupons, then item 2 gets all 5 for $35 off.
However, I need to develop a general algorithm which will handle different matrices and any number of items and coupons.
I suspect I will need to iterate through every possible combination to find the best price for n coupons. Does anyone here have any ideas?
This seems like a good candidate for dynamic programming:
//int[,] discountTable = new int[NumItems][NumCoupons+1]
// bestDiscount[i][c] means the best discount if you can spend c coupons on items 0..i
int[,] bestDiscount = new int[NumItems][NumCoupons+1];
// the best discount for a set of one item is just use the all of the coupons on it
for (int c=1; c<=MaxNumCoupons; c++)
bestDiscount[0, c] = discountTable[0, c];
// the best discount for [i, c] is spending x coupons on items 0..i-1, and c-x coupons on item i
for (int i=1; i<NumItems; i++)
for (int c=1; c<=NumCoupons; c++)
for (int x=0; x<c; x++)
bestDiscount[i, c] = Math.Max(bestDiscount[i, c], bestDiscount[i-1, x] + discountTable[i, c-x]);
At the end of this, the best discount will be the highest value of bestDiscount[NumItems][x]. To rebuild the tree, follow the graph backwards:
edit to add algorithm:
//int couponsLeft;
for (int i=NumItems-1; i>=0; i++)
{
int bestSpend = 0;
for (int c=1; c<=couponsLeft; c++)
if (bestDiscount[i, couponsLeft - c] > bestDiscount[i, couponsLeft - bestSpend])
bestSpend = c;
if (i == NumItems - 1)
Console.WriteLine("Had {0} coupons left over", bestSpend);
else
Console.WriteLine("Spent {0} coupons on item {1}", bestSpend, i+1);
couponsLeft -= bestSpend;
}
Console.WriteLine("Spent {0} coupons on item 0", couponsLeft);
Storing the graph in your data structure is also a good way, but that was the way I had thought of.
It's the Knapsack problem, or rather a variation of it. Doing some research on algorithms related to this problem will point you in the best direction.
I think dynamic programming should do this. Basically, you keep track of an array A[n, c] whose values mean the optimal discount while buying the n first items having spent c coupons. The values for a[n, 0] should be 0 for all values of n, so that is a good start. Also, A[0, c] is 0 for all c.
When you evaluate A[n,c], you loop over all discount offers for item n, and add the discount for that particular offer to A[n-1,c-p] where p is the price in coupons for this particular discount. A[n-1, c-p] must of course be calculated (in the same way) prior to this. Keep the best combination and store in the array.
A recursive implementation would probably give the cleanest implementation. In that case, you should find the answer in A[N,C] where N is the total number of items and C is the total number of available coupons.
This can be written as a linear programming problem. For most 'typical' problems, the simplex method is a fast, relatively simple way to solve such problems, or there are open source LP solvers available.
For your example:
Let 0 <= xi <= 1
x1 = One if one coupon is spent on item 1, zero otherwise
x2 = One if two coupons are spent on item 1, zero otherwise
x3 = One if one coupon is spent on item 2, zero otherwise
x4 = One if two coupons are spent on item 2, zero otherwise
x5 = One if three coupons are spent on item 3, zero otherwise
...
Assume that if I spend two coupons on item 1, then both x1 and x2 are one. This implies the constraint
x1 >= x2
With similar constraints for the other items, e.g.,
x3 >= x4
x4 >= x5
The amount saved is
Saved = 10 x1 + 5 x2 + 0 x3 + 5 x4 + 10 x5 + ...
If you want to find the most money saved with a fixed number of coupons, then you want to minimize Saved subject to the constraints above and the additional constraint:
coupon count = x1 + x2 + x3 + ...
This works for any matrix and number of items. Changing notation (and feeling sad that I can't do subscripts), let 0 <= y_ij <= 1 be one if j coupons are spent on item number i. The we have the constraints
y_i(j-1) >= y_ij
If the amount saved from spending j coupons on item i is M_ij, where we define M_i0 = 0, then maximize
Saved = Sum_ij (M_ij - M_i(j-1)) y_ij
subject to the above constraints and
coupon count = Sum_ij y_ij
(The italics formatting doesn't seem to be working here)
I suspect some kind of sorted list for memoizing each coupon-count can help here.
for example, if you have 4 coupons, the optimum is possibly:
using all 4 on something. You have to check all these new prices.
using 3 and 1. either the 3-item is the optimal solution for 3 coupons, or that item overlaps with the three top choices for 1-coupon items, in which case you need to find the best combination of one of the three best 1-coupon and 3-coupon items.
using 2 and 2. find top 3 2-items. if #1 and #2 overlap, #1 and #3 , unless they also overlap, in which case #2 and #3 don't.
this answer is pretty vague.. I need to put more thought into it.
This problem is similar in concept to the Traveling Salesman problem where O(n!) is the best for finding the optimal solution. There are several shortcuts that can be taken but they required lots and lots of time to discover, which I doubt you have.
Checking each possible combination is going to be the best use of your time, assuming we are dealing with small numbers of coupons. Make the client wait a bit instead of you spending years on it.