したがって、私があなたの質問を正しく理解していれば、以下の (Go での) コードで解決できると思います。各分布の積分が等しい (一方を他方に変換できることを意味する) と仮定できる場合は、移動するだけです。ディストリビューションを左から右に移動し、各ポイントで右からそこに移動する必要がある汚れの量、またはそこから左に移動する必要がある余分な汚れの量を把握します。いずれの場合も、必要な汚れはすべて取得できると想定できるため、一時的に「マイナス」の汚れがあっても問題ありません。
// Finds out how to move dirt to transform b into a.
// assumes that the integrals over a and b are equal
func earthMover(a, b []int) []int {
r := make([]int, len(a))
for i := 0; i < len(a); i++ {
// if diff is positive it means that there is too much dirt here and it
// must be moved to the right. if it is negative it means some dirt
// needs to be pulled in from the right. In either case dirt can be
// moved over multiple spaces.
diff := b[i] - a[i]
r[i] = diff
b[i] -= diff
if i < len(a) - 1 {
b[i+1] += diff
}
}
return r
}
ここに例があります。負の数は汚れが右から引き込まれることを意味し、正の数は左から右に押し込まれることを意味します。あなたのメトリクスについては、移動配列のすべての数値を合計するだけだと思うので、この場合の解は 5 です。
target: [ 3 0 1 0 2 6]
source: [ 1 1 5 0 1 4]
move: [-2 -1 3 3 2 0]
これで、実際にそれが必要な場合は、分布の加重平均または重心 (ダート) の違いを実際に探していることがわかりました。例えば:
0 1 2 3 4 5
target: [ 3 0 1 0 2 6]
weighted: 0 +0 +2 +0 +8+30 = 40
source: [ 1 1 5 0 1 4]
weighted: 0 +1+10 +0 +4+20 = 35
ご覧のとおり、ターゲットの重心からソースの重心を差し引いた値は、先ほど取得した数値で、40 - 35 = 5 です。