Let me give you an example of what I mean. Let's say I have N=3
items { A, B, C }
and want to consolidate them into K
groups (0 < K < N
). For example, consolidating them into K=2
groups might produce the result
{ {A, B}, {C} }
I have a function Cost(X, Y) >= 0
that returns the cost of consolidating item X
into item Y
. For example, if Cost(A, B) = 10
and Cost(B, C) = 15
then producing
{ {A, B}, {C} }
costs 10
and producing
{ {A}, {B, C} }
costs 15
.
The cost function is not commutative (It's not always true that Cost(X, Y) = Cost(Y, X)
).
What I want to do is find an algorithm for the least costly consolidation into K
groups.
For example, let's say the costs are
Cost(A, B) = 12
Cost(B, A) = 4
Cost(A, C) = 5
Cost(C, A) = 11
Cost(B, C) = 3
Cost(C, B) = 20
and I want to consolidate into K=1
groups. The least costly would be
B -> C
A -> C
at a cost of 8
.
I'm trying to figure out a generalization of how to determine this.
How I think it should start out is to order all the costs:
Cost(B, C) = 3
Cost(B, A) = 4
Cost(A, C) = 5
Cost(C, A) = 11
Cost(A, B) = 12
Cost(C, B) = 20
The item in the above list will always be a one of the moves in the consolidation process:
B -> C
Now, what I suspect needs to happen is iterate through the rest of the list and see if each consolidation.
The next item in the list is B -> A
. Since I already moved B
to C
, skip over this one.
The next item is A -> C
. Since A
hasn't yet been consolidated into a group, this is a valid consolidation.
Now we're done since we have K=1
groups, { {A, B, C} }
.
I'm wondering how to write this algorithm.
To be more concrete, here's a C# setup:
using System;
using System.Collections.Generic;
using System.Linq;
public class Widget
{
public int Distance { get; set; }
public int Weight { get; set; }
public static int Cost(Widget w1, Widget w2)
{
// returns the cost of consolidating w1 into w2
return Math.Abs(w1.Distance - w2.Distance) * w1.Weight;
}
}
public class Program
{
public static void Main()
{
var widgets = new List<Widget>()
{
new Widget() { Distance = 10, Weight = 1 },
new Widget() { Distance = 20, Weight = 1 },
new Widget() { Distance = 30, Weight = 1 },
};
var tuples = from x in widgets
from y in widgets
where !x.Equals(y)
select Tuple.Create(x,y);
var ordered = from t in tuples
orderby Widget.Cost(t.Item1, t.Item2)
select t;
int K = 2;
int sum = 0;
// ... What to do here???
Console.WriteLine(sum); // should write 10
}
}
FYI, this isn't a homework problem or anything. I'm doing it for fun.